package com.xbongbong.pro.statistics.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.xbongbong.paas.constant.ChartStatisticsConstant;
import com.xbongbong.paas.constant.FieldAttrConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.domain.entity.PaasFormRefEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.AddressEnum;
import com.xbongbong.paas.enums.AggTypeEnum;
import com.xbongbong.paas.enums.BIProductReformEnum;
import com.xbongbong.paas.enums.BiEsAliasEnum;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.EsAliasEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.bi.XbbTableRefEnum;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.model.PaasFormRefModel;
import com.xbongbong.paas.pojo.StageFindPojo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.RegexUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.bi.commons.pojo.vo.GroupSqlVO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.IntervalTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.service.stage.StageFindStrategy;
import com.xbongbong.pro.service.stage.factory.StageFindFactory;
import com.xbongbong.pro.statistic.constant.RelatedProductConstant;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.enums.LinkDetailFieldEnum;
import com.xbongbong.pro.statistic.help.ChartResultHelp;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.pojo.SlaveSourcePojo;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistic.util.ChartUtil;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.WorkOrderTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ContractPerformanceEnum;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.xbongbong.paas.constant.XbbConstant.JSON_EXTRACT;
import static com.xbongbong.paas.constant.XbbConstant.JSON_EXTRACT_ARRAY_RAW;
import static com.xbongbong.paas.constant.XbbConstant.JSON_EXTRACT_RAW;
import static com.xbongbong.paas.constant.XbbConstant.JSON_EXTRACT_STRING;
import static com.xbongbong.paas.constant.XbbConstant.STRING_CONSTANT;
import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;

/**
 * 生成查询语句sql的帮助类
 *
 * @ClassName InitSqlHelper
 * @Author 梁鲁江
 * 创建时间 2021/10/20 16:05
 * 修改时间  2021/10/20 16:05
 **/
@Component
public class InitSqlHelper {
    public Logger LOG = LoggerFactory.getLogger(getClass());
    @Resource
    private ComputedHelp computedHelp;
    @Resource
    private ChartResultHelp chartResultHelp;
    @Resource
    private PaasFormRefModel paasFormRefModel;
    @Resource
    private CommonHelper commonHelper;
    @Resource
    private  DisplayHelper displayHelper;
    @Resource
    private DescribeTableHelper describeTableHelper;
    @Resource
    private StatisticsTableVOHelper statisticsTableVOHelper;

    private static InitSqlHelper instance = new InitSqlHelper();

    public static String currentSubFormName = null;

    private static HashMap<Integer, String> subFormHashMap = Maps.newHashMap();
    private static HashMap<Integer, String> teamUserHashMap = Maps.newHashMap();

    private InitSqlHelper() {
    }

    public static synchronized InitSqlHelper getInstance() {
        if (Objects.isNull(instance)) {
            instance = new InitSqlHelper();
        }
        return instance;
    }


    /**
     * 查询表的自定义展现数据
     *
     * @param fieldAttrPojoList
     * @param summaryAttrList
     * @param tableHead
     * @param parseAttrMap
     * @param summaryAttrMap
     * @param chartEntity
     * @throws XbbException
     */
    public Pair<List<String>, HashMap<String, Set<String>>> displayAttrAssemble(List<ChartFieldAttrPojo> fieldAttrPojoList, List<FieldAttrPojo> summaryAttrList
            , JSONArray tableHead, Map<JSONObject, FieldAttrPojo> parseAttrMap, Map<String, FieldAttrPojo> summaryAttrMap,
                                                                                ChartEntity chartEntity, boolean isSingle, Map<String, String> sortMap,GroupSqlVO groupSqlVO) throws XbbException {
        List<String> fieldsList = new ArrayList<>();
        JSONObject formIdAttr = chartEntity.getFormIdAttr();
        Map<Long, String> formIdTableMap = commonHelper.getFormIdTableMap(chartEntity, isSingle);
        HashMap<String, Set<String>> selectItemsMap = Maps.newHashMap();
        List<String> columnAlisaList = new ArrayList<>();
        List<String> subQuerySqlOfCountList = new ArrayList<>();
        //查询表若只选择负责人/协同人时 需要取到对应的dataId 作为查询条件
        if (isSingle) {
            fieldsList.add(FieldTypeEnum.ID.getAlias());
            columnAlisaList.add(FieldTypeEnum.ID.getAlias());
        } else {
            for (Map.Entry<String, Object> entry : formIdAttr.entrySet()) {
                String formId = entry.getKey();
                Object value = entry.getValue();
                JSONObject valueObj = new JSONObject((Map<String, Object>) value);
                String alais = valueObj.getString(StringConstant.DATA_ID);
                fieldsList.add(formIdTableMap.get(Long.valueOf(formId)) + ".id AS " + alais);
                columnAlisaList.add(alais);
            }
        }
        if (CollectionsUtil.isNotEmpty(fieldAttrPojoList)) {
            for (ChartFieldAttrPojo fieldAttrPojo : fieldAttrPojoList) {
                String attr = fieldAttrPojo.getAttr();
                Long formId = fieldAttrPojo.getFormId();
                //处理headName
                boolean specialFlag = handleHeadName(chartEntity, isSingle, fieldsList, formIdTableMap, fieldAttrPojo, tableHead, parseAttrMap,columnAlisaList);
                //上面加过的后面就不用再添加
                if (specialFlag) {
                    continue;
                }

                addFieldaliasList(selectItemsMap, isSingle, fieldsList, null, formIdTableMap, fieldAttrPojo, attr, formId, sortMap, chartEntity,null,columnAlisaList,subQuerySqlOfCountList);
                if (Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()) || Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_MULTI.getType())
                        || Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_RECEIVER.getType())) {
                    attr = fieldAttrPojo.getLinkedText();
                    JSONObject linkedJsonObject = fieldAttrPojo.getLinkedAttr();
                    if(linkedJsonObject!=null){
                        if (EsUtil.setInData(linkedJsonObject.getInteger("fieldType"))) {
                            String jsonExtract = JSON_EXTRACT;
                            if (Objects.equals(FieldTypeEnum.NUM.getType(), linkedJsonObject.getInteger("fieldType")) || Objects.equals(FieldTypeEnum.STAR.getType(), linkedJsonObject.getInteger("fieldType"))) {
                                jsonExtract = XbbConstant.JSON_EXTRACT_DOUBLE;
                            } else if (Objects.equals(FieldTypeEnum.DATETIME.getType(), linkedJsonObject.getInteger("fieldType"))) {
                                jsonExtract = XbbConstant.JSON_EXTRACT_INT;
                            }
                            String formIdSuff = formIdTableMap.get(formId);
                            String extractString = CommonHelper.getExtractString(jsonExtract, formIdSuff,attr);
                            if (!isSingle) {
                                //多表LinkedText是被修改过的字段，LinkedAttr里面的attr是原始字段
                                extractString = CommonHelper.getExtractString(jsonExtract, formIdSuff,linkedJsonObject.getString("attr"));
                            }
                            fieldsList.add(extractString + " AS " + attr);
                            columnAlisaList.add(attr);
                        } else {
                            // //TODO  不在data内？   外层关联限制下应该都在data内
//                        fieldsList.add(s + " AS " + attr);
                        }
                    }
                } else if (FieldTypeEnum.BIRTHDAY.getType().equals(fieldAttrPojo.getFieldType())) {
                    //生日字段处理
                    String linkedText = fieldAttrPojo.getLinkedText();
                    fieldsList.add(XbbConstant.JSON_EXTRACT_INT + "(" + formIdTableMap.get(formId) + ".`data`,'" + linkedText + "')  AS " + linkedText);
                    columnAlisaList.add(linkedText);
                }

            }
        }
        displayHelper.handleSummary(summaryAttrList, tableHead, parseAttrMap, summaryAttrMap, isSingle);
        Pair<List<String>, HashMap<String, Set<String>>> listHashMapPair = new ImmutablePair<>(fieldsList, selectItemsMap);
        groupSqlVO.setSummaryColumnAlisa(columnAlisaList);
        groupSqlVO.setSubQuerySqlOfCountList(subQuerySqlOfCountList);
        return listHashMapPair;
    }

    /**
     * @return void
     * @throws
     * @Description 添加查询字段到map里
     * @Date 14:55 2021/12/22
     * @Param [formIdTableMap, selectItemsMap, formId, col]
     **/

    protected void addSelectCol(Map<Long, String> formIdTableMap, HashMap<String, Set<String>> selectItemsMap, Long formId, String col) {
        if (Objects.isNull(formIdTableMap) || Objects.isNull(selectItemsMap) || Objects.isNull(formId) || StringUtils.isEmpty(col) || col.contains(FieldAttrConstant.CO_USER_ID)) {
            return;

        }
        String key = formIdTableMap.get(formId);
        Set<String> vSet = selectItemsMap.get(key);
        if (Objects.isNull(vSet)) {
            vSet = Sets.newHashSet();
        }
        vSet.add(col);
        selectItemsMap.put(key, vSet);
    }

    public static boolean getIsMaxPermission(ChartResultPojo chartResultPojo) {
        if (chartResultPojo != null) {
            UserVO loginUser = chartResultPojo.getLoginUser();
            if (loginUser != null) {
                return loginUser.isMaxDataPermission(true);
            }
        }
        return false;
    }

    /**
     * @return java.lang.String
     * @author gzt
     * @Description updatetime字段 as 需要特殊处理
     * @Date 9:30 2022/1/17
     **/

    protected String renameUpdateTime(String col) {
        if (Objects.equals(XbbConstant.UPDATE_TIME, col)) {
            col = MessageFormat.format("t{0}", col);
        }
        return col;
    }

    /**
     * @param colWithPre
     * @return java.lang.String
     * @throws
     * @Description 由于特殊的去重方式，update字段需要特殊处理,as 后原字段重命名
     * @Date 9:28 2022/1/13
     **/
    protected String renameUpdateTimeWithPre(String colWithPre) {
        if (StringUtils.isNotEmpty(colWithPre) && colWithPre.contains(XbbConstant.UPDATE_TIME)) {
            colWithPre = colWithPre.replaceAll(XbbConstant.UPDATE_TIME, "t" + XbbConstant.UPDATE_TIME);
        }
        return colWithPre;
    }

    /**
     * @param col
     * @return java.lang.String
     * @throws
     * @Description 生成argMax拼接串【由于特殊的去重方式，update字段需要特殊处理,as 后原字段重命名】
     * @Date 9:28 2022/1/13
     * @Param
     **/

    public String generatargMax(String col) {
        if (!col.equals(XbbConstant.UPDATE_TIME)) {
            return "argMax(" + col + ",update_time) as " + col;
        } else {
            return "argMax(" + col + ",update_time) as t" + col;
        }
    }


    /**
     * 拼装表头
     *
     * @param chartEntity
     * @param isSingle
     * @param fieldsList
     * @param formIdTableMap
     * @param fieldAttrPojo
     * @param tableHead
     * @param parseAttrMap
     * @return boolean
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2021/11/22 13:36
     * @version 1.0
     */
    public boolean handleHeadName(ChartEntity chartEntity, boolean isSingle, List<String> fieldsList, Map<Long, String> formIdTableMap, ChartFieldAttrPojo fieldAttrPojo, JSONArray tableHead, Map<JSONObject, FieldAttrPojo> parseAttrMap,List<String> columnAlisaList) {
        JSONObject headName = displayHelper.setHeadField(chartEntity.getChartType(), fieldAttrPojo);
        // 处理穿透链接详情页的参数
        dealPenetrateLinkDetail(headName, fieldAttrPojo, chartEntity);
        boolean specialFlag = specialTableTitleHandle(fieldAttrPojo, fieldsList, headName, isSingle, chartEntity, formIdTableMap,columnAlisaList);
        tableHead.add(headName);
        parseAttrMap.put(headName, fieldAttrPojo);
        return specialFlag;
    }

    /**
     * 处理穿透链接详情页的参数
     *
     * @param jsonObject    表头字段
     * @param fieldAttrPojo 当前展示字段
     * @param chartEntity   图表结构
     */
    public void dealPenetrateLinkDetail(JSONObject jsonObject, ChartFieldAttrPojo fieldAttrPojo, ChartEntity chartEntity) {

        Integer saasMark = fieldAttrPojo.getSaasMark();
        if (!Objects.equals(BasicConstant.ONE, saasMark)) {
            return;
        }

        Integer businessType = fieldAttrPojo.getBusinessType();
        List<String> supportLinkDetailList = LinkDetailFieldEnum.getLinkDetailAttrByBusinessType(businessType);
        if (CollectionsUtil.isEmpty(supportLinkDetailList)) {
            return;
        }

        String attr;
        if (EsUtil.getSingle(chartEntity)) {
            attr = fieldAttrPojo.getAttr();
        } else {
            attr = fieldAttrPojo.getOriginalAttr();
        }
        if (!supportLinkDetailList.contains(attr)) {
            return;
        }

        // 下面是链接详情需要的参数
        jsonObject.put(ChartStatisticsConstant.BUSINESS_TYPE, businessType);
        jsonObject.put(ChartStatisticsConstant.SUB_BUSINESS_TYPE, businessType);
        jsonObject.put(ChartStatisticsConstant.SAAS_MARK, BasicConstant.ONE);
        jsonObject.put(ChartStatisticsConstant.IS_LINK_DETAIL, BasicConstant.ONE);

    }

    /**
     * 添加字段带别名
     *
     * @param isSingle
     * @param fieldsList      放在表头上的名字（分组字段也要放在表头返回）
     * @param groupFieldsList 分组字段
     * @param formIdTableMap
     * @param fieldAttrPojo
     * @param attr
     * @param formId
     * @return
     */
    public HashMap<String, Set<String>> addFieldaliasList(HashMap<String, Set<String>> selectItemsMap, boolean isSingle, List<String> fieldsList, List<String> groupFieldsList, Map<Long, String> formIdTableMap, FieldAttrPojo fieldAttrPojo, String attr, Long formId, Map<String, String> sortMap, ChartEntity chartEntity,Map<String,FieldAttrPojo> comboFieldMap,List<String> columnAlisaList,List<String> subQuerySqlOfCountList) throws XbbException {
        //TODO 区分在colums和group BY的字段
        Integer fieldType = fieldAttrPojo.getFieldType();
        String sortAttr = null;
        sortAttr = sortMap.get(attr);
        /*if(isSingle){
            sortAttr = sortMap.get(attr);
        }else {
            sortAttr = sortMap.get(fieldAttrPojo.getOriginalAttr());
        }*/
        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(fieldAttrPojo.getBusinessType(),fieldType)) {
            String jsonExtract = getExtractFuntion(fieldType, null);
            if (EsHelper.isDateTimeByFieldType(fieldType)) {
                String originalAttr = attr;
                if (!isSingle) {
                    originalAttr = fieldAttrPojo.getOriginalAttr();
                }
                IntervalTypeEnum intervalTypeEnum = IntervalTypeEnum.getByFormatStr(fieldAttrPojo.getDateGroupType());
                String s = XbbConstant.JSON_EXTRACT_INT + "(" + formIdTableMap.get(formId) + ".`data`,'" + originalAttr + "')";
                String s2 = "";
                //注意下面这个没有写AS  别名，否则会造成相同别名数据格式的不一致
                if (groupFieldsList != null) {
                    String s1 = "";
                    if(Objects.equals(intervalTypeEnum.getDateFunctions(),IntervalTypeEnum.YEAR_QUARTER.getDateFunctions())){
                        s1 = "toInt64(toDateTime64(multiIf(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Q')=='1', CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-01-01'),formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Q') =='2',CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-04-01'),formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Q')=='3', CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-07-01'),  CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-10-01')),0))";
                    }else if(Objects.equals(intervalTypeEnum.getDateFunctions(),IntervalTypeEnum.YEAR_WEEK.getDateFunctions())){
                        s1 = "toInt64(toDateTime64(formatDateTime(subtractDays(toDateTime64(" +
                                s +
                                ",0), toDayOfWeek(toDateTime64(" +
                                s +
                                ",0))-1), '" +
                                IntervalTypeEnum.YEAR_MONTH_DAY.getFormatPlaceholder() +
                                "'),0))";
                    }else {
                        s1 = "toInt64(toDateTime64(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '" +
                                intervalTypeEnum.getFormatPlaceholder() +
                                "'),0))";
                    }
                    s2 = "if(" + XbbConstant.JSON_HAS + "(" + formIdTableMap.get(formId) + ".`data`,'" + originalAttr + "')" + "," + s1 + ",null)";
                    groupFieldsList.add(s2);
                    if (StringUtil.isNotEmpty(sortAttr) && (Objects.equals(sortAttr.trim(), "asc") || Objects.equals(sortAttr.trim(), "desc"))) {
                        sortMap.put(attr, s2 + " " + sortAttr);
                    }
                    fieldsList.add("MAX(" + s2 + ") AS " + attr);
                } else {
                    if (StringUtil.isNotEmpty(sortAttr) && (Objects.equals(sortAttr.trim(), "asc") || Objects.equals(sortAttr.trim(), "desc"))) {
                        sortMap.put(attr, s + "  " + sortAttr);
                    }
                    s2 = "if(" + XbbConstant.JSON_HAS + "(" + formIdTableMap.get(formId) + ".`data`,'" + originalAttr + "')" + "," + s + ",null)";
                    fieldsList.add(s2 + " AS " + attr);
                    columnAlisaList.add(attr);
                }
            } else if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(), fieldType)) {
                try {
                    computedHelp.addComputedField(chartEntity,fieldAttrPojo, AggTypeEnum.getByAlias(fieldAttrPojo.getAggType()),PaasConstant.LEFT,selectItemsMap,formIdTableMap,Maps.newHashMap(),fieldsList,sortMap,new ArrayList<>(),subQuerySqlOfCountList,columnAlisaList);
                } catch (XbbException e) {
                    LOG.error("计算字段的公式格式有问题", e);
                    throw e;
                }
            } else if ((Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType) || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType))) {
                String s;
                String key = attr;
                if (!isSingle) {
                    key = fieldAttrPojo.getOriginalAttr();
                }
                if (attr.contains(".")) {
                    String[] keyArray = key.split("\\.");
                    s = JSON_EXTRACT_STRING +
                            "(" +
                            JSON_EXTRACT_RAW +
                            "(" + formIdTableMap.get(formId) +
                            ".`data`, '" +
                            keyArray[0] +
                            "'), '" +
                            //多表时取originalAttr字段，但该字段后没有拼 `.省市区`，防索引越界异常这里取attr的字段值
                            attr.split("\\.")[1] +
                            "')";

                } else {
                    s =
                            JSON_EXTRACT_RAW +
                                    "(" + formIdTableMap.get(formId) +
                                    ".`data`, '" +
                                    key +
                                    "')";
                }
                if (groupFieldsList != null) {
                    String field = s + " AS `" + attr.replaceAll("\\.", "_") + "`";
                    fieldsList.add(field);
                    groupFieldsList.add(field);
                } else {
                    boolean containsAddress = attr.contains(BusinessConstant.PROVINCE) || attr.contains(BusinessConstant.CITY) || attr.contains(BusinessConstant.DISTRICT);
                    String field = s + " AS " + attr;
                    //兼容穿透查询
                    if (containsAddress) {
                        field = s + " AS `" + attr.replaceAll("\\.", "_") + "`";
                    }
                    fieldsList.add(field);
                    columnAlisaList.add(field.split(XbbConstant.AS)[1]);
                }
            } else {
                String tName = formIdTableMap.get(formId);
                //String dataInAttr = jsonExtract + "(" + tName + ".`data`,'" + attr + "')";
                String dataInAttr = CommonHelper.getExtractString(jsonExtract,tName,attr);
                if (!isSingle) {
                    // 多表取原attr
                    String originalAttr = fieldAttrPojo.getOriginalAttr();
                    dataInAttr = CommonHelper.getExtractString(jsonExtract, tName, originalAttr);
                    if (StringUtils.equals(XbbTableRefEnum.CONTRACT_PERFORMANCE.getTableName(), tName)) {
                        String key = StringUtil.getDataBaseString(ContractPerformanceEnum.getRealAttr(originalAttr));
                        dataInAttr = MessageFormat.format("{0}{1}{2}", tName, StringConstant.POINT, key);
                    }
                }
                String field = dataInAttr + " AS " + attr;
                fieldsList.add(field);
                columnAlisaList.add(attr);
                if (groupFieldsList != null) {
                    groupFieldsList.add(field);
                }
                if (StringUtil.isNotEmpty(sortAttr) && (Objects.equals(sortAttr.trim(), "asc") || Objects.equals(sortAttr.trim(), "desc"))) {
                    sortMap.put(attr, field + " " + sortAttr);
                }
                if(statisticsTableVOHelper.isComboFieldSort(chartEntity,fieldType,sortMap)){
                    comboFieldMap.put(field,fieldAttrPojo);
                }
            }
        } else {
            String originalAttr = attr;
            if (!isSingle && Objects.nonNull(fieldAttrPojo.getOriginalAttr())) {
                originalAttr = fieldAttrPojo.getOriginalAttr();
                addSelectCol(formIdTableMap, selectItemsMap, formId, generatargMax(StringUtil.getDataBaseString(originalAttr)));
            }
            if (EsHelper.isDateTimeByFieldType(fieldType)) {
                IntervalTypeEnum intervalTypeEnum = IntervalTypeEnum.getByFormatStr(fieldAttrPojo.getDateGroupType());
                String mode = "";
                if(Objects.equals(intervalTypeEnum.getDateFunctions(),IntervalTypeEnum.YEAR_WEEK.getDateFunctions())){
                    mode = "," + XbbConstant.MODE;
                }
                if (isSingle) {
                    addSelectCol(formIdTableMap, selectItemsMap, formId, generatargMax(StringUtil.getDataBaseString(originalAttr)));
                }
                //注意下面这个没有写AS  别名，否则会造成相同别名数据格式的不一致
                if (groupFieldsList != null) {
                    String s = formIdTableMap.get(formId) + "." + renameUpdateTime(StringUtil.getDataBaseString(originalAttr));
                    String s1 = "";
                    if(Objects.equals(intervalTypeEnum.getDateFunctions(),IntervalTypeEnum.YEAR_QUARTER.getDateFunctions())){
                        s1 = "toInt64(toDateTime64(multiIf(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Q')=='1', CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-01-01'),formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Q') =='2',CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-04-01'),formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Q')=='3', CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-07-01'),  CONCAT(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '%Y') ,'-10-01')),0))";
                    }else if(Objects.equals(intervalTypeEnum.getDateFunctions(),IntervalTypeEnum.YEAR_WEEK.getDateFunctions())){
                        s1 = "toInt64(toDateTime64(formatDateTime(subtractDays(toDateTime64(" +
                                s +
                                ",0), toDayOfWeek(toDateTime64(" +
                                s +
                                ",0))-1), '" +
                                IntervalTypeEnum.YEAR_MONTH_DAY.getFormatPlaceholder() +
                                "'),0))";
                    }else {
                        s1 = "toInt64(toDateTime64(formatDateTime(toDateTime64(" +
                                s +
                                ",0), '" +
                                intervalTypeEnum.getFormatPlaceholder() +
                                "'),0))";
                    }
                    groupFieldsList.add(s1);
                    if (StringUtil.isNotEmpty(sortAttr) && (Objects.equals(sortAttr.trim(), "asc") || Objects.equals(sortAttr.trim(), "desc"))) {
                        sortMap.put(attr, s1 + " " + sortAttr);
                    }
                    fieldsList.add("MAX(" + s1 + ") AS " +  StringUtil.getDataBaseString(attr));
                } else {
                    fieldsList.add(formIdTableMap.get(formId) + "." + renameUpdateTime(StringUtil.getDataBaseString(originalAttr)) + " AS " + StringUtil.getDataBaseString(attr));
                    columnAlisaList.add(StringUtil.getDataBaseString(attr));
                    if (StringUtil.isNotEmpty(sortAttr) && (Objects.equals(sortAttr.trim(), "asc") || Objects.equals(sortAttr.trim(), "desc"))) {
                        sortMap.put(attr, formIdTableMap.get(formId) + "." + renameUpdateTime(StringUtil.getDataBaseString(originalAttr)) + " " + sortAttr);
                    }
                }
            } else if (EsHelper.isTeamLogicByFieldType(fieldAttrPojo.getFieldType(), fieldAttrPojo.getBusinessType())) {
                String teamName = getTeamNameByBusinessType(fieldAttrPojo.getBusinessType());
                // 获取团队展示字段格式
                String field = getTeamDisplayAttr(fieldAttrPojo, formId, chartEntity, teamName,formIdTableMap);
                fieldsList.add(field);
                columnAlisaList.add(field);
                if (groupFieldsList != null) {
                    groupFieldsList.add(field);
                }
                if (StringUtil.isNotEmpty(sortAttr) && (Objects.equals(sortAttr.trim(), "asc") || Objects.equals(sortAttr.trim(), "desc"))) {
                    sortMap.put(attr, field + " " + sortAttr);
                }
            } else {
                String field = formIdTableMap.get(formId) + "." + renameUpdateTime(StringUtil.getDataBaseString(originalAttr)) + " AS " + renameUpdateTime(StringUtil.getDataBaseString(attr));
                fieldsList.add(field);
                columnAlisaList.add(field);
                addSelectCol(formIdTableMap, selectItemsMap, formId, generatargMax(StringUtil.getDataBaseString(originalAttr)));
                if (groupFieldsList != null) {
                    groupFieldsList.add(field);
                }
                if (StringUtil.isNotEmpty(sortAttr) && (Objects.equals(sortAttr.trim(), "asc") || Objects.equals(sortAttr.trim(), "desc"))) {
                    sortMap.put(attr, field + " " + sortAttr);
                }
                if(statisticsTableVOHelper.isComboFieldSort(chartEntity,fieldType,sortMap)){
                    comboFieldMap.put(field,fieldAttrPojo);
                }
            }

        }
        return selectItemsMap;
    }

    /**
     * 获取展示字段
     *
     * @param fieldAttrPojo 当前字段
     * @param formId        表单id
     * @param chartEntity   图表实体
     * @param tableName      团队表名
     * @return 展示字段
     */
    private static String getTeamDisplayAttr(FieldAttrPojo fieldAttrPojo, Long formId, ChartEntity chartEntity, String tableName, Map<Long, String> formIdTableMap) {
        String field = null;
        int teamIdx = EsUtil.getTeamIdx(chartEntity, formId);
        String tableIdx = formIdTableMap.get(formId).substring(XbbTableRefEnum.getByCode(fieldAttrPojo.getBusinessType()).getTableName().length());
        if(StringUtil.isNotEmpty(tableIdx)){
            tableName += tableIdx;
        }
        if (FieldTypeEnum.OWNERID.getType().equals(fieldAttrPojo.getFieldType())) {
            field = tableName + "." + XbbConstant.TEAM_MAIN + " AS myTeamMain_" + teamIdx;
        } else if (FieldTypeEnum.COUSERID.getType().equals(fieldAttrPojo.getFieldType())) {
            field = tableName + "." + XbbConstant.TEAM_CO + " AS myTeam_" + teamIdx;
        }
        return field;
    }

    /**
     * 特殊字段 展示标题处理
     *
     * @param fieldAttrPojo 字段属性详情
     * @param fieldsList    展示字段
     * @param headName      回显标题属性值
     * @param isSingle      是否为单表
     * @param chartEntity   图表实体
     * @return
     * @author zhouwq
     * @date 2019/6/3 17:25
     */
    private  boolean specialTableTitleHandle(FieldAttrPojo fieldAttrPojo, List<String> fieldsList, JSONObject headName, Boolean isSingle, ChartEntity chartEntity, Map<Long, String> formIdTableMap,List<String> columnAlisaList) {
        boolean specialFlag = false;
        Integer fieldType = fieldAttrPojo.getFieldType();
        if (FieldTypeEnum.isSubFormType(fieldType)) {
            specialFlag = true;
            displayHelper.subFieldItems(fieldAttrPojo, headName);
            String attr = fieldAttrPojo.getAttr();
            Long formId = fieldAttrPojo.getFormId();
            if (fieldsList != null){
                fieldsList.add(JSON_EXTRACT_ARRAY_RAW + "(" + formIdTableMap.get(formId) + ".`data`,'" + attr + "')" + " AS " + attr);
                columnAlisaList.add(attr);
            }
        } else if (FieldTypeEnum.OWNERID.getType().equals(fieldType) || FieldTypeEnum.COUSERID.getType().equals(fieldType)) {
            specialFlag = true;
            //TODO
            Long formId = fieldAttrPojo.getFormId();
            // 根据主表查到团队表
            Integer businessType = fieldAttrPojo.getBusinessType();
            // 访客计划这张表不需要走字表逻辑
            if (Objects.equals(XbbRefTypeEnum.COMMUNICATE_PLAN.getCode(), businessType)) {
                return false;
            }
            String tableName = getTeamNameByBusinessType(businessType);

            if (StringUtil.isEmpty(tableName)) {
                return false;
            }
            if (fieldsList != null) {
                String field = getTeamDisplayAttr(fieldAttrPojo, formId, chartEntity, tableName,formIdTableMap);
                fieldsList.add(field);
                //查询表调用时，fieldsList跟columnAlisaList同时不为空
                columnAlisaList.add(field);
            }
        }
        return specialFlag;
    }




    /**
     * 排序
     *
     * @param sortMap
     * @param parseAttrMap
     * @param summaryAttrList
     * @param chartEntity
     * @return
     */
    public String sortByFiled(Map<String, String> sortMap, Map<JSONObject, FieldAttrPojo> parseAttrMap, List<FieldAttrPojo> summaryAttrList, ChartEntity chartEntity) {
        String sortField = "update_time";
        SortOrder order = SortOrder.DESC;
        sortMap = displayHelper.getSortMap(chartEntity, sortMap);
        boolean isSingle = !Objects.equals(chartEntity.getMuti(), BasicConstant.ZERO);
        boolean isContains = false;
        if (summaryAttrList != null) {
            for (FieldAttrPojo fieldAttrPojo : summaryAttrList) {
                String attr = fieldAttrPojo.getAttr();
                if (StringUtil.isNotEmpty(sortMap.get("field"))) {
                    String field = sortMap.get("field");
                    if (field.contains(attr)) {
                        isContains = true;
                    }
                }
            }
            if (!isContains) {
                return sortField + " " + order;
            }
        }
        boolean mulTable = false;
        if (sortMap != null && !sortMap.isEmpty()) {
            sortField = (StringUtil.isEmpty(sortMap.get("field")) ? sortField : sortMap.get("field"));
            String[] sortFieldStr = sortField.split("&");
            String type = null;
            String location = null;
            //TODO   多个的处理
            if (sortFieldStr.length > BasicConstant.TWO) {
                type = sortFieldStr[2];
                sortField = sortFieldStr[1];
                location = sortFieldStr[0];
                mulTable = true;
            }
            if (BasicConstant.TWO.equals(sortFieldStr.length)) {
                type = sortFieldStr[1];
                sortField = sortFieldStr[0];
            }
            if (StringUtil.isNotEmpty(type)) {
                if (EsUtil.setInData(Integer.valueOf(type))) {
//                        sortField = isSingle ? "data." + sortField : sortField;
                    //TODO  还没有加表名
                    sortField = "JSONExtractRaw(`data`," + sortField + ") ";
//                        sortField = isSingle ? "data." + sortField : sortField;
                    if (mulTable) {
                        sortField = location + sortField;
                    }
                } else {
                    if (mulTable) {
                        sortField = location + sortField;
                    }
                }
            }
            if (SortOrder.ASC.toString().equals(sortMap.get(BasicConstant.SORT))) {
                order = SortOrder.ASC;
            }
        }
        return sortField + " " + order;
    }

    /**
     * 筛选条件
     *
     * @param chartEntity
     * @param isPublicFlag
     * @return
     * @throws XbbException
     */
    public boolean parseConditionIntersection(Map<String, StringBuffer> fliterMap, ChartEntity chartEntity, boolean isPublicFlag) throws XbbException {
        JSONArray conditionJson = chartEntity.getFilter();
        conditionJson = JSON.parseArray(conditionJson.toJSONString());
        JSONArray searchJson = chartEntity.getSearch();
        searchJson = JSON.parseArray(searchJson.toJSONString());
        boolean isSingle;
        if (Objects.isNull(chartEntity.getSingle())) {
            isSingle = true;
        } else {
            isSingle = EsUtil.getSingle(chartEntity);
        }
        String corpid = chartEntity.getCorpid();
        JSONObject formIdAttr = chartEntity.getFormIdAttr();
        Long driverFormId = chartEntity.getDriverSources().getLong("formId");
        Integer driverBusiness = chartEntity.getDriverSources().getInteger("businessType");
        StringBuffer driveBuffer = fliterMap.get(driverFormId.toString());
        initSqlString(corpid, driverFormId, driverBusiness, fliterMap, driveBuffer, null);
        // 主表默认筛选逻辑
        addDefaultFilter(corpid, driverFormId, driverBusiness, fliterMap, formIdAttr);
        // 多表
        handleWorkOrderV2VersionFilter(isSingle, driverBusiness, conditionJson);
        handleFilter4WorkOrderV2(driverBusiness, conditionJson);
        if (!isSingle) {
            JSONArray slaveSources = chartEntity.getSlaveSources();
            if (slaveSources != null) {
                for (int i = 0; i < slaveSources.size(); i++) {
                    JSONObject slaveSource = slaveSources.getJSONObject(i);
                    Integer businessType = slaveSource.getInteger("businessType");
                    Long formId = slaveSource.getLong("formId");
                    StringBuffer slaveBuffer = fliterMap.get(formId.toString());
                    initSqlString(corpid, formId, businessType, fliterMap, slaveBuffer, null);
                    // 从表默认筛选逻辑
                    addDefaultFilter(corpid, formId, businessType, fliterMap, formIdAttr);
                }
            }
        }
        // 产品分类筛选逻辑
        parseProductCategory(corpid, chartEntity, fliterMap, formIdAttr);
        // 地图显示范围及钻取
        chartResultHelp.parseMap(chartEntity,conditionJson);
        //漏斗图需要根据filter > search来判断是否需要进行维度字段的范围控制
        funnelItemMark(chartEntity,conditionJson,searchJson);
        //查询条件和筛选条件放在一起
        if (searchJson != null && searchJson.size() > 0) {
            conditionJson.addAll(searchJson);
        }
        // 筛选条件处理常用和自定义动态
        describeTableHelper.searchCondition(conditionJson,chartEntity.getCorpid(),chartEntity.getId());
        //获取formId和saasMark的对应关系，团队处理需要区别saas表和paas表
        JSONObject driveSources = chartEntity.getDriverSources();
        JSONArray slaveSources = chartEntity.getSlaveSources();
        Map<Integer, Boolean> sourcesMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        boolean isTeamLogic = EsHelper.isTeamLogicByBusinessType(driveSources.getInteger("businessType"));
        sourcesMap.put(driveSources.getInteger("formId"), isTeamLogic);
        if (slaveSources != null) {
            for (int i = 0; i < slaveSources.size(); i++) {
                JSONObject slaveSource = slaveSources.getJSONObject(i);
                boolean isTeamLogicSlave = EsHelper.isTeamLogicByBusinessType(slaveSource.getInteger("businessType"));
                sourcesMap.put(slaveSource.getInteger("formId"), isTeamLogicSlave);
            }
        }
        if (!isSingle) {
            if (conditionJson.size() > 0) {
                for (Object o : conditionJson) {
                    JSONObject filterJson = (JSONObject) o;
                    Integer fieldType = filterJson.getInteger("fieldType");
                    Long formId = filterJson.getLong("formId");
                    boolean isTeam = sourcesMap.get(formId.intValue());
                    boolean isTeamAttr = FieldTypeEnum.OWNERID.getType().equals(fieldType) || FieldTypeEnum.COUSERID.getType().equals(fieldType);
                    if (isTeam && isTeamAttr) {
                        int teamIdx = EsUtil.getTeamIdx(chartEntity, formId);
                        String teamAttr = "myTeam_" + teamIdx;
                        filterJson.put("attr", teamAttr);
                    }
                }
            }
        }
        isPublicFlag = ChartUtil.isPublicFlag(conditionJson);
        parseFilterOrSearchCondition(corpid, fliterMap, conditionJson, isSingle, true, sourcesMap, isPublicFlag);
        return isPublicFlag;
    }

    /**
     * 有的情况没有businessType,导致无法判断是否为data外字段（for 新工单）
     * @param driverBusiness
     * @param conditionJson
     */
    private void handleFilter4WorkOrderV2(Integer driverBusiness, JSONArray conditionJson) {
        if (!Objects.equals(XbbRefTypeEnum.WORK_ORDER_V2.getCode(), driverBusiness)
                && !Objects.equals(XbbRefTypeEnum.WORK_ORDER_V2_NODE_LOG_INFO.getCode(), driverBusiness)) {
            return;
        }
        List<String> workOrderV2NodeLogInfoFields = Arrays.asList("nodeId", "stayTime", "startTime", "startSignTime",
                "finishSignBackTime", "acceptInTime", "startInTime", "finishInTime", "finishFinishUser");
        for (Object o : conditionJson) {
            JSONObject filterJson = (JSONObject) o;
            if (workOrderV2NodeLogInfoFields.contains(filterJson.getString("attr"))) {
                filterJson.put(XbbConstant.BUSINESS_TYPE, XbbRefTypeEnum.WORK_ORDER_V2_NODE_LOG_INFO.getCode());
            }
        }
    }

    /**
     * 新工单多表关联时，移除filter中的versionId信息
     * @param isSingle
     * @param businessType
     * @param conditionJson
     */
    private void handleWorkOrderV2VersionFilter(boolean isSingle, Integer businessType, JSONArray conditionJson) {
        if (isSingle || !Objects.equals(XbbRefTypeEnum.WORK_ORDER_V2.getCode(), businessType)) {
            return;
        }
        for (Iterator<Object> iterator = conditionJson.iterator(); iterator.hasNext(); ) {
            Object o = iterator.next();
            JSONObject filterJson = (JSONObject) o;
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER_V2_NODE_LOG_INFO.getCode(), filterJson.getInteger(XbbConstant.BUSINESS_TYPE))) {
                iterator.remove();
            }
        }
    }

    public void funnelItemMark(ChartEntity chartEntity, JSONArray conditionJson, JSONArray searchJson) {
        //非漏斗图不进行操作
        if(!Objects.equals(ChartTypeEnum.FUNNEL.getCode(),chartEntity.getChartType())){
            return;
        }
        //获取漏斗图维度字段，只会有一个
        JSONArray chartClassify = chartEntity.getChartClassify();
        JSONObject classifyJSONObject = chartClassify.getJSONObject(0);
        //优先处理filter
        boolean filterFlag = dealCondition(conditionJson,classifyJSONObject,chartEntity);
        //其次判断search
        if(!filterFlag){
            dealCondition(searchJson,classifyJSONObject,chartEntity);
        }
    }

    private boolean dealCondition(JSONArray conditionJson,JSONObject classifyJSONObject,ChartEntity chartEntity) {
        String corpid = chartEntity.getCorpid();
        boolean flag = false;
        if(CollectionUtils.isNotEmpty(conditionJson)){
            String classifyAttr = classifyJSONObject.getString("attr");
            for (int i = 0; i < conditionJson.size(); i++) {
                JSONObject jsonObject = conditionJson.getJSONObject(i);
                Integer filedType = jsonObject.getInteger("fieldType");
                if (!Objects.equals(FieldTypeEnum.STAGE_THRUSTER.getType(),filedType)){
                    continue;
                }
                String attr = jsonObject.getString("attr");
                if (!classifyAttr.equals(attr)){
                    continue;
                }
                //重置维度字段的items
                resetFunnelClassicFieldItems(chartEntity,classifyJSONObject,jsonObject,corpid);
                flag = true;
                break;
            }
        }
        return flag;
    }

    public void parseFilterOrSearchCondition(String corpid, Map<String, StringBuffer> fliterMap, JSONArray conditionJson, boolean isSingle, boolean isFilterCondition,
                                             Map<Integer, Boolean> sourcesMap, boolean isPublicFlag) throws XbbException {
        if (conditionJson.size() > 0) {
            HashMap<String, HashSet<String>> subFormMap = Maps.newHashMap();
            conditionJson = getSortArrayJson(conditionJson);
            for (Object o : conditionJson) {
                JSONObject filterJson = (JSONObject) o;
                ConditionsEntityExt condition = JSONObject.parseObject(filterJson.toJSONString(), ConditionsEntityExt.class);
                String parentAttr = filterJson.getString("parentAttr");
                if (parentAttr != null && !Objects.equals(parentAttr, "")) {
                    JSONObject parentObj = filterJson.getJSONObject("parentSubFormAttr");
                    Integer parentFieldType = parentObj == null ? null : parentObj.getInteger("fieldType");
                    if (!Objects.equals(parentFieldType, FieldTypeEnum.CONTACT_NUMBER.getType())) {
                        condition.setSubAttr(parentAttr);
                    }
                }
                boolean emptyFlag = Objects.equals(condition.getSymbol(), ConditionEnum.EMPTY.getSymbol()) || Objects.equals(condition.getSymbol(), ConditionEnum.NOEMPTY.getSymbol());
                //如果value值为空则跳过
                if (!emptyFlag && (Objects.isNull(condition.getValue()) || condition.getValue().isEmpty())) {
                    continue;
                }
                if (!emptyFlag && (Objects.isNull(condition.getValue()) || Objects.isNull(condition.getValue().get(0)) || "".equals(condition.getValue().get(0)))) {
                    continue;
                }
                boolean isNeedRelationSubForm = isNeedRelationSubFormTable(filterJson.getInteger("businessType"), parentAttr);
                if (isNeedRelationSubForm) {
                    getSubFormAttrCountMap(subFormMap, filterJson, parentAttr);
                }
                Long formId = filterJson.getLong("formId");
                boolean isTeam = sourcesMap.get(formId.intValue());
                ConditionEnum conditionEnum = ConditionEnum.getConditionEnum(condition.getSymbol());
                conditionSymbolChoose(corpid, fliterMap, conditionEnum, condition, isTeam, isPublicFlag, isSingle, filterJson.getInteger("businessType"));
            }
            subFormMap.forEach((k, v) -> {
                if (v.size() > 0) {
                    StringBuffer stringBuffer = fliterMap.get(k);
                    v.stream().forEach(a -> stringBuffer.append(")"));
                }
            });
        }

    }

    private void resetFunnelClassicFieldItems(ChartEntity chartEntity,JSONObject classifyJSONObject,JSONObject conditionObj,String corpid) {
        Long stageVersionId = conditionObj.getLong("stageVersionId");
        if(Objects.isNull(stageVersionId)){
            //兼容特殊情况（该逻辑上线前已经设置过阶段推进器字段筛选了,默认选择启用的阶段）
            JSONArray items = conditionObj.getJSONArray("items");
            JSONObject jsonObject = items.getJSONObject(0);
            stageVersionId = jsonObject.getLong("stageProcessId");
        }

        FieldAttrPojo fieldAttrPojo = classifyJSONObject.toJavaObject(FieldAttrPojo.class);
        Long formId = fieldAttrPojo.getFormId();
        Integer businessType = fieldAttrPojo.getBusinessType();
        Integer saasMark = fieldAttrPojo.getSaasMark();
        StageFindStrategy stageFindStrategy = StageFindFactory.getStageFindStrategy(saasMark, businessType);
        List<? extends PaasStageEntity> stageList = stageFindStrategy.findStageList(corpid, new StageFindPojo(formId, stageVersionId, EnableEnum.OPEN, null));
        List<ItemPoJo> itemPoJoList = new ArrayList<>();
        for (PaasStageEntity paasStageEntity : stageList) {
            ItemPoJo itemPoJo = new ItemPoJo();
            itemPoJo.setValue(paasStageEntity.getCode());
            itemPoJo.setText(paasStageEntity.getName());
            itemPoJo.setStageProcessId(stageVersionId);
            itemPoJoList.add(itemPoJo);
        }
        classifyJSONObject.put("items",itemPoJoList);
        JSONArray chartClassify = chartEntity.getChartClassify();
        chartClassify.set(0,classifyJSONObject);
    }

    /**
     * @param subFormMap
     * @param filterJson
     * @param parentAttr
     * @return void
     * @throws
     * @Description 获得主表、从表子表单筛选去重后数量，用不空值括号添加
     * @Date 21:52 2022/1/12
     **/

    private void getSubFormAttrCountMap(HashMap<String, HashSet<String>> subFormMap, JSONObject filterJson, String parentAttr) {
        if (!Objects.isNull(filterJson) && StringUtils.isNotEmpty(parentAttr)) {
            String formId = filterJson.getLong("formId").toString();
            if (StringUtils.isNotEmpty(formId)) {
                HashSet<String> subFormSet = subFormMap.get(formId);
                if (Objects.isNull(subFormSet)) {
                    subFormSet = Sets.newHashSet();
                    subFormSet.add(parentAttr);
                    subFormMap.put(formId, subFormSet);
                } else if (!subFormSet.contains(parentAttr)) {
                    subFormSet.add(parentAttr);
                    subFormMap.put(formId, subFormSet);
                }
            }
        }
    }

    /**
     * @param conditionJson
     * @return com.alibaba.fastjson.JSONArray
     * @Description 获取排序后的JsonArray
     * @Date 16:53 2022/1/10
     **/

    private JSONArray getSortArrayJson(JSONArray conditionJson) {
        JSONArray jsonArray = null;
        if (conditionJson != null) {
            List<JSONObject> list = JSONArray.parseArray(conditionJson.toJSONString(), JSONObject.class);
            Collections.sort(list, new Comparator<JSONObject>() {
                @Override
                public int compare(JSONObject o1, JSONObject o2) {
                    String a = o1.getString("parentAttr");
                    String b = o2.getString("parentAttr");
                    if (a == null) {
                        a = "a";
                    }
                    if (b == null) {
                        b = "a";
                    }
                    return a.compareTo(b);
                }
            });
            jsonArray = JSONArray.parseArray(list.toString());
        }
        return jsonArray;
    }

    /**
     * 自定义图表条件语句组装(筛选,穿透)
     *
     * @param conditionEnum 筛选类型
     * @param condition     筛选详情
     * @param businessType  业务code
     */
    private void conditionSymbolChoose(String corpid, Map<String, StringBuffer> fliterMap, ConditionEnum conditionEnum,
                                       ConditionsEntityExt condition, boolean isTeam, boolean isPublicFlag, boolean isSingle, Integer businessType) {
        subFormParseValue(condition);
        //subAttr不为空为子表单字段 且单表情况下
        if (Objects.nonNull(condition.getSubAttr()) && isSingle) {
            subFormConditionSymbolChoose(corpid, fliterMap, conditionEnum, condition, isSingle, businessType);
        } else if (FieldTypeEnum.OWNERID.getType().equals(condition.getFieldType()) && isTeam) {
            teamConditionSymbolChoose(fliterMap, conditionEnum, condition, isTeam, 1, isPublicFlag, isSingle, businessType);
        } else if (FieldTypeEnum.COUSERID.getType().equals(condition.getFieldType()) && isTeam) {
            teamConditionSymbolChoose(fliterMap, conditionEnum, condition, isTeam, 0, false, isSingle, businessType);
        } else if (FieldTypeEnum.BIRTHDAY.getType().equals(condition.getFieldType())) {
//            conditionBirthday(boolQueryBuilder, (int) condition.getValue().get(0), null);
        } else if (FieldTypeEnum.ADDRESS.getType().equals(condition.getFieldType())) {
            biAddressConditionSymbolChoose(corpid, fliterMap, conditionEnum, condition, isSingle);
        } else {
            commonConditionSymbolChoose(corpid, fliterMap, conditionEnum, condition, isSingle, businessType);
        }
    }

    public static void subFormParseValue(ConditionsEntityExt condition) {
        List<Object> values = condition.getValue();
        List<Object> list = new ArrayList<>();
        Integer fieldType = condition.getFieldType();
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
        if (condition.getPenetrateFlag() != null && Objects.equals(1, condition.getPenetrateFlag())) {
            Object value;
            if (CollectionsUtil.isEmpty(values)) {
                value = "";
                list.add(value);
                condition.setValue(list);
            }
        } else {
            if (fieldTypeEnum != null) {
                switch (fieldTypeEnum) {
                    case USER:
                    case CREATORID:
                    case OWNERID:
                    case COUSERID:
                    case USER_GROUP:
                        if (CollectionsUtil.isNotEmpty(values)) {
                            for (Object obj : values) {
                                if (obj instanceof String) {
                                    list.add(obj);
                                } else if (obj instanceof JSONObject) {
                                    JSONObject jsonObject = (JSONObject) obj;
                                    String userId = jsonObject.getString(ParameterConstant.USER_ID);
                                    list.add(userId);
                                }
                            }
                        }
                        condition.setValue(list);
                        break;
                    case DEPT:
                    case DEPT_GROUP:
                    case DEPARTMENTID:
                        if (CollectionsUtil.isNotEmpty(values)) {
                            for (Object obj : values) {
                                if (obj instanceof String || obj instanceof Integer || obj instanceof Long) {
                                    list.add(obj);
                                } else if (obj instanceof JSONObject) {
                                    JSONObject jsonObject = (JSONObject) obj;
                                    String userId = jsonObject.getString("id");
                                    list.add(userId);
                                }
                            }
                        }
                        condition.setValue(list);
                        break;
                    case CATEGORY_ID:
                        if (CollectionsUtil.isNotEmpty(values)) {
                            for (Object obj : values) {
                                if (obj instanceof Integer) {
                                    list.add(obj);
                                } else if (obj instanceof JSONObject) {
                                    JSONObject jsonObject = (JSONObject) obj;
                                    Integer categoryId = jsonObject.getInteger("id");
                                    list.add(categoryId);
                                } else if (obj instanceof String) {
                                    list.add(Long.parseLong(obj.toString()));
                                }
                            }
                        }
                        condition.setValue(list);
                        break;
                    case CONTACT_NUMBER:
                        condition.setAttr(condition.getAttr() + StringConstant.POINT + StringConstant.PHONE_TEL_ATTR);
                        break;
                    case ADDRESS:
                        //地址特殊处理
                        String attr;
                        String[] attrs = condition.getAttr().split("\\.");
                        if (attrs.length > 0) {
                            attr = attrs[attrs.length - 1];
                            if (AddressEnum.getByAlias(attr) != null) {
                                Object value = null;
                                if (AddressEnum.CITY.equals(AddressEnum.getByAlias(attr))) {
                                    if (Objects.equals(values.size(), BasicConstant.ONE)) {
                                        value = values.get(0);
                                    } else {
                                        value = values.get(1);
                                    }
                                } else if (AddressEnum.DISTRICT.equals(AddressEnum.getByAlias(attr))) {
                                    if (Objects.equals(values.size(), BasicConstant.ONE)) {
                                        value = values.get(0);
                                    } else {
                                        value = values.get(2);
                                    }
                                }
                                if (value != null) {
                                    List valueList = new ArrayList();
                                    valueList.add(value);
                                    condition.setValue(valueList);
                                }
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }

/*    private static void subFormConditionSymbolChoose(Map<Long,StringBuffer>  fliterMap, ConditionEnum conditionEnum, ConditionsEntityExt condition) {
        String attr = condition.getAttr();
        String subFormAttr = "";
        //获取当前字段的attr 并去除父attr前缀
        if (attr.contains(StringConstant.POINT)) {
            String[] attrArray = attr.split("\\.");
            attr = attrArray[1];
            subFormAttr = attrArray[2];
        }
        condition.setAttr("data." + subFormAttr);
        BoolQueryBuilder teamQueryBuilder = boolQuery();
        //TODO ???
        teamQueryBuilder.filter(termQuery("attr.keyword", attr));
        commonConditionSymbolChoose(teamQueryBuilder, conditionEnum, condition);
        boolQueryBuilder.filter(JoinQueryBuilders.hasChildQuery("sub_form_data",teamQueryBuilder, ScoreMode.Max));
    }*/

    /**
     * 公用解析（特殊的请单独写）
     *
     * @param conditionEnum
     * @param condition
     */
    public void commonConditionSymbolChoose(String corpid, Map<String, StringBuffer> fliterMap, ConditionEnum conditionEnum,
                                            ConditionsEntityExt condition, boolean isSingle, Integer businessType) {
        String attr = condition.getAttr();
        Integer fieldType = condition.getFieldType();
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
        if (!isSingle) {
            attr = Objects.isNull(condition.getOriginalAttr()) ? attr : condition.getOriginalAttr();
        }
        if (!attr.contains(StringConstant.POINT)) {
            attr = StringUtil.getDataBaseString(attr);
        }
        Long formId = condition.getFormId();
        StringBuffer stringBuffer = fliterMap.get(formId.toString());
        // text特殊处理
        Object value = null;
        Object secondVal = null;
        List<Object> valList = condition.getValue();
        // 使用临时数组接受前端传参类型不同，方便下面IN逻辑拼接sql
        List<Object> tempList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(valList)) {
            // 文本转换
            for (int i = 0, valListSize = valList.size(); i < valListSize; i++) {
                Object nowVal = valList.get(i);
                if(nowVal instanceof String){
                    String newVal = "'\"" + nowVal + "\"'";
                    tempList.add(newVal);
                }
                if(nowVal instanceof Integer){
                    String newVal = "'" + nowVal + "'";
                    tempList.add(newVal);
                }
                Object val = handleText(fieldType, nowVal);
                valList.set(i, val);
            }
            // 第一个值
            value = valList.get(0);
            // 第二个值
            if (valList.size() > 1) {
                secondVal = valList.get(1);
            }
        }

        //生成初始的sql拼装语句
        stringBuffer = initSqlString(corpid, formId, condition.getBusinessType(), fliterMap, stringBuffer, attr);
        switch (conditionEnum) {
            case EQUAL:
                if (valList.size() == 1) {
                    if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType)
                            || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
                        // and  JSONExtractString(JSONExtractRaw(data,'address_1'),'city') ='杭州市'
                        Map<String, Objects> addressJson = (Map) value;
                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.SPACE)
                                .append("(").append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append("'").append(BusinessConstant.CITY).append("'").append(" = ").append("'").append(addressJson.get(BusinessConstant.CITY)).append("'");
                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.SPACE)
                                .append("(").append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append("'").append(BusinessConstant.DISTRICT).append("'").append(" = ").append("'").append(addressJson.get(BusinessConstant.DISTRICT)).append("'");
                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.SPACE)
                                .append("(").append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append("'").append(BusinessConstant.ADDRESS).append("'").append(" = ").append("'").append(addressJson.get(BusinessConstant.ADDRESS)).append("'");
                    } else if (Objects.equals(FieldTypeEnum.COMBO_CHECK.getType(), fieldType) || Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), fieldType)
                            || Objects.equals(FieldTypeEnum.USER_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.LABEL.getType(), fieldType)) {
                        // 多选框只有一个值时,外层限制了等于
//                        select id,JSONExtractArrayRaw(`data`,'text_20') FROM  tb_saas_customer prewhere  corpid ='1'
//                        AND  has(JSONExtractArrayRaw(`data`,'text_20'),'"国庆"')
//                         AND  hasAll(JSONExtractArrayRaw(`data`,'text_20'),['"中秋"','"国庆"'])
                        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                            String leftMarks = "['\"";
                            String rightMarks = "\"'])";
                            if (Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType)) {
                                leftMarks = "['";
                                rightMarks = "'])";
                            }
                            if (attr.contains(StringConstant.POINT)) {
                                String[] attrArray = attr.split("\\.");
                                String subForm = attrArray[0];
                                if (StringUtils.isNotEmpty(subForm) && subForm.contains("_")) {
                                    if (isNeedRelationSubFormTable(businessType, subForm)) {
                                        stringBuffer.append(XbbConstant.AND).append("hasAll(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attrArray[1] + "'), " + leftMarks + value + rightMarks).append(XbbConstant.SPACE);
                                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + leftMarks + value + rightMarks).append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attrArray[1] + "')" + ")");
                                    } else {
                                        stringBuffer.append(XbbConstant.AND).append("hasAll(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "'), " + leftMarks + value + rightMarks).append(XbbConstant.SPACE);
                                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + leftMarks + value + rightMarks).append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ")");
                                    }
                                }
                            } else {
                                stringBuffer.append(XbbConstant.AND).append("hasAll(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "'), " + leftMarks + value + rightMarks).append(XbbConstant.SPACE);
                                stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + leftMarks + value + rightMarks).append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ")");
                            }
                        }
                    } else if (value instanceof List) {
                        //TODO
                        /*select id,JSONExtractArrayRaw(`data`,'text_20') FROM  tb_saas_customer prewhere  corpid ='1'
                        AND  hasAll(JSONExtractArrayRaw(`data`,'text_20'),['"新建一条客户吧"','"国庆"','"中秋"'])
                        AND LENGTH (['"新建一条客户吧"','"国庆"','"中秋"']) = LENGTH (JSONExtractArrayRaw(`data`,'text_20'))*/
                        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                            //TODO hasAll
                            stringBuffer.append(XbbConstant.AND).append("has(+" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "'), " + "'" + value + "')").append(XbbConstant.SPACE);
                            stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + value + ")").append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,' " + attr + "')'" + ")");
                        }
                        //TODO 当前if选项内应该都在data内

                    } else if (Objects.equals(FieldTypeEnum.SWITCH.getType(), fieldType)) {
                        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                            attr = XbbConstant.JSON_EXTRACT_INT + "(`data`,'" + attr + "')";
                        }
                        stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" = ").append(value);
                    } else if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_SINGLE.getType(), fieldType)) {
                        // 关联单选存的是只有long类型和String
                        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                            String s = JSON_EXTRACT;
                            if (!(value instanceof String)) {
                                s = XbbConstant.JSON_EXTRACT_INT;
                            }
                            attr = getStringWithFunN(s, attr);
                        }
                        stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" = ").append(value);
                    } else if (Objects.equals(FieldTypeEnum.COMBO_NUM.getType(), fieldType)) {
                        if (Objects.equals(businessType, XbbRefTypeEnum.CONTRACT_PERFORMANCE.getCode())) {
                            attr = StringUtil.getDataBaseString(ContractPerformanceEnum.getRealAttr(attr));
                        } else {
                            attr = XbbConstant.JSON_EXTRACT_INT + "(`data`,'" + attr + "') ";
                        }
                        stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" = ").append(value);
                    } else {
                        // 简单的相等
                        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                            attr = getFunctionAttr(attr, fieldType, value, null, businessType, stringBuffer);
                        } else {
                            if (value instanceof String) {
                                attr = StringUtil.getDataBaseString(attr);
                            }
                        }
                        if (attr != null && StringUtils.contains(attr, XbbConstant.ARRAY_ELEMENT)) {
                            handlerMainSubForm(stringBuffer, attr, XbbConstant.EQUAL, value);
                            break;
                        }
                        stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" = ").append(value);
                    }

                } else {
                    if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                        String s = JSON_EXTRACT_RAW;
                        attr = getStringWithFunN(s, attr);
                    }
                    if (CollectionsUtil.isNotEmpty(valList)) {
                        stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" IN ").append(valList);
                        // // 这两个字段需要回显下级，特殊处理
                        // if (Objects.equals(FieldTypeEnum.AREA.getType(), condition.getFieldType()) || Objects.equals(FieldTypeEnum.PURCHASEABLE_GOODS.getType(), condition.getFieldType())) {
                        //     stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" IN ").append(valList);
                        // } else {
                        //     // 多选的情况下的相等
                        //     for (Object valueItem : valList) {
                        //         // multipleBool.should(termsQuery(key, valueItem));
                        //     }
                        // }
                    }
                }
                break;
            case NOEQUAL:
                //SELECT JSONExtractRaw('{"a": 0, "b": [-100, 200.0, 300]}', 'a') = '[-100, 200.0, 300]';
                //TODO 也要根据类型区分使用的函数
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    /*String s = XbbConstant.JSON_EXTRACT_RAW;
                    FieldTypeEnum fieldTypeE = FieldTypeEnum.getFieldTypeEnum(fieldType);
                    if (!StringUtils.equals(fieldTypeE.getEsalias(), EsAliasEnum.TEXT.getEsAlias())) {
                        attr = s + "(`data`,'" + attr + "') ";
                    }else {
                        attr = s + "(`data`,'" + attr + "') ";
                    }*/
                    attr = getFunctionAttr(attr, fieldType, value, null, businessType, stringBuffer);
                    //String extractFuntion = getExtractFuntion(fieldType, value);

                }
                if (attr != null && StringUtils.contains(attr, XbbConstant.ARRAY_ELEMENT)) {
                    handlerMainSubForm(stringBuffer, attr, XbbConstant.NOT_EQUAL, value);
                    break;
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" != ").append(value);
                break;
            case EMPTY:
                String str = attr;
                FieldTypeEnum fieldTypeE = FieldTypeEnum.getFieldTypeEnum(fieldType);
                if (fieldTypeE != null) {
                    String esalias = fieldTypeE.getEsalias();
                    if (Objects.equals(FieldTypeEnum.NUM, fieldTypeE) || (StringUtils.equals(esalias, EsAliasEnum.LONG.getEsAlias()) ||
                            StringUtils.equals(esalias, EsAliasEnum.DATE.getEsAlias()))) {
                        stringBuffer.append(XbbConstant.AND).append(" JSONHas(data, '" + attr + "') = 0");
                        break;
                    }
                }

                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    //str = XbbConstant.JSON_EXTRACT_STRING + "(`data`,'" + attr + "')";
                    str = getFunctionAttr(attr, fieldType, value, JSON_EXTRACT, businessType, stringBuffer);
                }
                if (FieldTypeEnum.DATETIME.getType().equals(fieldType)
                        || FieldTypeEnum.STAR.getType().equals(fieldType)
                        || FieldTypeEnum.DEPARTMENTID.getType().equals(fieldType)
                        || FieldTypeEnum.ADDTIME.getType().equals(fieldType)
                        || FieldTypeEnum.LINK_DATA.getType().equals(fieldType)
                        || FieldTypeEnum.UPDATETIME.getType().equals(fieldType)) {
                    stringBuffer.append(XbbConstant.AND).append(str).append(XbbConstant.SPACE).append(" = ").append(0);
                } else if (fieldTypeEnum != null
                        && (FieldTypeEnum.TEXT.getEsalias().equals(fieldTypeEnum.getEsalias())
                        || FieldTypeEnum.ADDRESS.getEsalias().equals(fieldTypeEnum.getEsalias())
                        || FieldTypeEnum.UPLOAD.getEsalias().equals(fieldTypeEnum.getEsalias())
                        || FieldTypeEnum.NUM.getEsalias().equals(fieldTypeEnum.getEsalias()))) {
                    if (str != null && StringUtils.contains(str, XbbConstant.ARRAY_ELEMENT)) {
                        handlerMainSubForm(stringBuffer, str, XbbConstant.EQUAL, "''");
                        break;
                    }

                    stringBuffer.append(XbbConstant.AND).append(str).append(XbbConstant.SPACE).append(" = ").append("''");
                } else if (Objects.equals(FieldTypeEnum.COMBO_CHECK.getType(), fieldType) || Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), fieldType)
                        || Objects.equals(FieldTypeEnum.USER_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.LABEL.getType(), fieldType)) {
                    //stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ") = 0 ");
                    handlerSubformComboEmpty(attr, stringBuffer, "=", businessType);
                    //stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + str + "')" + ") = 0 ");
                } else {
                    // 空数组也只需这个
                    stringBuffer.append(XbbConstant.AND).append(str).append(XbbConstant.SPACE).append("IS NULL");
                }
                break;
            case NOEMPTY:
                String noEmptyStr = attr;
                FieldTypeEnum fieldTypeN = FieldTypeEnum.getFieldTypeEnum(fieldType);
                if (fieldTypeN != null) {
                    String esalias = fieldTypeN.getEsalias();
                    if (Objects.equals(FieldTypeEnum.NUM, fieldTypeN) || (StringUtils.equals(esalias, EsAliasEnum.LONG.getEsAlias()) ||
                            StringUtils.equals(esalias, EsAliasEnum.DATE.getEsAlias()))) {
                        stringBuffer.append(XbbConstant.AND).append(" JSONHas(data, '" + attr + "') = 1");
                        break;
                    }
                }
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    //noEmptyStr = XbbConstant.JSON_EXTRACT_STRING + "(`data`,'" + attr + "')";
                    noEmptyStr = getFunctionAttr(attr, fieldType, value, JSON_EXTRACT, businessType, stringBuffer);
                }
                if (FieldTypeEnum.DATETIME.getType().equals(fieldType)
                        || FieldTypeEnum.STAR.getType().equals(fieldType)
                        || FieldTypeEnum.DEPARTMENTID.getType().equals(fieldType)
                        || FieldTypeEnum.ADDTIME.getType().equals(fieldType)
                        || FieldTypeEnum.LINK_DATA.getType().equals(fieldType)
                        || FieldTypeEnum.UPDATETIME.getType().equals(fieldType)) {
                    stringBuffer.append(XbbConstant.AND).append(noEmptyStr).append(XbbConstant.SPACE).append(" != ").append(0);
                } else if (fieldTypeEnum != null
                        && (FieldTypeEnum.TEXT.getEsalias().equals(fieldTypeEnum.getEsalias())
                        || FieldTypeEnum.ADDRESS.getEsalias().equals(fieldTypeEnum.getEsalias())
                        || FieldTypeEnum.UPLOAD.getEsalias().equals(fieldTypeEnum.getEsalias())
                        || FieldTypeEnum.NUM.getEsalias().equals(fieldTypeEnum.getEsalias()))) {
                    if (noEmptyStr != null && StringUtils.contains(noEmptyStr, XbbConstant.ARRAY_ELEMENT)) {
                        handlerMainSubForm(stringBuffer, noEmptyStr, XbbConstant.NOT_EQUAL, "''");
                        break;
                    }
                    stringBuffer.append(XbbConstant.AND).append(noEmptyStr).append(XbbConstant.SPACE).append(" != ").append("''");
                } else if (Objects.equals(FieldTypeEnum.COMBO_CHECK.getType(), fieldType) || Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), fieldType)
                        || Objects.equals(FieldTypeEnum.USER_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.LABEL.getType(), fieldType)) {
                    //stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ") > 0 ");
                    handlerSubformComboEmpty(attr, stringBuffer, ">", businessType);
                } else {
                    stringBuffer.append(XbbConstant.AND).append(noEmptyStr).append(XbbConstant.SPACE).append("IS NOT NULL");
                }
                break;
            case INCLUDE:
                if (Objects.equals(FieldTypeEnum.COMBO_CHECK.getType(), fieldType) || Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), fieldType)
                        || Objects.equals(FieldTypeEnum.USER_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.LABEL.getType(), fieldType)) {
                    // 多选框只有一个值时,外层限制了等于
//                        select id,JSONExtractArrayRaw(`data`,'text_20') FROM  tb_saas_customer prewhere  corpid ='1'
//                        AND  has(JSONExtractArrayRaw(`data`,'text_20'),'"国庆"')
//                         AND  hasAll(JSONExtractArrayRaw(`data`,'text_20'),['"中秋"','"国庆"'])
                    if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                        StringBuilder s = new StringBuilder();
                        if (valList.size() > 0) {
                            s.append("( ");
                            String marks = "['\"";
                            String marksSuff = "\"'])";
                            if (Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType)) {
                                marks = "['";
                                marksSuff = "'])";
                            }
                            for (int i = 0; i < valList.size(); i++) {
                                if (i > 0) {
                                    s.append(" or ");
                                }
                                if (attr.contains(StringConstant.POINT)) {
                                    String[] attrArray = attr.split("\\.");
                                    String attr1;
                                    String subForm = attrArray[0];
                                    if (StringUtils.isNotEmpty(subForm) && subForm.indexOf("_") != -1) {
                                        if (isNeedRelationSubFormTable(businessType, subForm)) {
                                            attr1 = JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[1] + "')";
                                            s.append("hasAll(").append(attr1)
                                                    .append(", ").append(marks).append(valList.get(i)).append(marksSuff);
                                        } else {
                                            attr1 = attrArray[1];
                                            String arrayRaw = "arrayJoin(" + JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[0] + "'))";
                                            s.append("hasAll(").append(JSON_EXTRACT_ARRAY_RAW).append("(" + arrayRaw + ",'").append(attr1)
                                                    .append("'), ").append(marks).append(valList.get(i)).append(marksSuff);
                                        }
                                    }

                                } else {
                                    s.append("hasAll(").append(JSON_EXTRACT_ARRAY_RAW).append("(`data`,'").append(attr)
                                            .append("'), ").append(marks).append(valList.get(i)).append(marksSuff);
                                }
                            }
                            s.append(" )");
                        }
                        stringBuffer.append(XbbConstant.AND).append(s).append(XbbConstant.SPACE);
                    }
                } else {
                    Set<Object> valueSet = new HashSet<>();
                    for (Object obj : valList) {
                        if (Objects.nonNull(obj)) {
                            valueSet.add(obj);
                        }
                    }
                    if (!valueSet.isEmpty()) {
                        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                            attr = getFunctionAttr(attr, fieldType, value, JSON_EXTRACT, businessType, stringBuffer);
                        }
                        stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" IN ").append(valueSet);
                    } else {
                        stringBuffer.append(XbbConstant.AND).append(" 1=0 ");
                    }
                }
                break;
            case LIKE:
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    //attr = XbbConstant.JSON_EXTRACT_STRING + "(`data`,'" + attr + "')";
                    attr = getFunctionAttr(attr, fieldType, value, JSON_EXTRACT, businessType, stringBuffer);
                }
                if (value instanceof String) {
                    String substring = value.toString().substring(1, value.toString().length() - 1);
                    value = "'%" + substring + "%'";
                }
                if (attr != null && StringUtils.contains(attr, "arrayElement")) {
                    handlerMainSubForm(stringBuffer, attr, XbbConstant.LIKE, value);
                    break;
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" LIKE ").append(value);
                break;
            case NOLIKE:
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    //attr = XbbConstant.JSON_EXTRACT_STRING + "(`data`,'" + attr + "')";
                    attr = getFunctionAttr(attr, fieldType, value, JSON_EXTRACT, businessType, stringBuffer);
                }
                if (value instanceof String) {
                    String substring = value.toString().substring(1, value.toString().length() - 1);
                    value = "'%" + substring + "%'";
                }
                if (attr != null && StringUtils.contains(attr, XbbConstant.ARRAY_ELEMENT)) {
                    handlerMainSubForm(stringBuffer, attr, XbbConstant.NOT_LIKE, value);
                    break;
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" NOT LIKE ").append(value);
                break;
            case ALLINCLUDE:
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    if (Objects.equals(FieldTypeEnum.COMBO_CHECK.getType(), fieldType) || Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), fieldType)
                            || Objects.equals(FieldTypeEnum.USER_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.LABEL.getType(), fieldType)) {
                        if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                            String vals = "";
                            if (valList != null) {
                                vals = valList.stream().map(e -> "'\"" + e + "\"'").collect(Collectors.joining(","));
                                if (Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldType)) {
                                    vals = valList.stream().map(e -> "'" + e + "'").collect(Collectors.joining(","));
                                }
                            }
                            /*if (attr.contains(StringConstant.POINT)) {
                                String[] attrArray = attr.split("\\.");
                                attr = attrArray[1];
                                String array_raw = "arrayJoin("+JSON_EXTRACT_ARRAY_RAW+ "(data,'" + attrArray[0] + "'))";
                                stringBuffer.append(XbbConstant.AND).append("hasAll(" + JSON_EXTRACT_ARRAY_RAW + "("+array_raw+",'" + attr + "'), " + "[" + vals + "])").append(XbbConstant.SPACE);
                                stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "([" + vals + "])")       .append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "("+array_raw+",'" + attr + "')" + ")");
                            }*/
                            if (attr.contains(StringConstant.POINT)) {
                                String[] attrArray = attr.split("\\.");
                                String attr1;
                                String subForm = attrArray[0];
                                if (StringUtils.isNotEmpty(subForm) && subForm.indexOf("_") != -1) {
                                    if (isNeedRelationSubFormTable(businessType, subForm)) {
                                        attr1 = JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[1] + "')";
                                        stringBuffer.append(XbbConstant.AND).append("hasAll(" + attr1 + ", " + "[" + vals + "])").append(XbbConstant.SPACE);
                                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "([" + vals + "])").append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[1] + "')" + ")");
                                    } else {
                                        attr = attrArray[1];
                                        String arrayRaw = "arrayJoin(" + JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[0] + "'))";
                                        stringBuffer.append(XbbConstant.AND).append("hasAll(" + JSON_EXTRACT_ARRAY_RAW + "(" + arrayRaw + ",'" + attr + "'), " + "[" + vals + "])").append(XbbConstant.SPACE);
                                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "([" + vals + "])").append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(" + arrayRaw + ",'" + attr + "')" + ")");
                                    }
                                }
                            } else {
                                //StringJoiner stringJoiner = new StringJoiner(",","[","]");
                                stringBuffer.append(XbbConstant.AND).append("hasAll(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "'), " + "[" + vals + "])").append(XbbConstant.SPACE);
                                stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "([" + vals + "])").append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ")");
                            }
                            /*} else {
                                stringBuffer.append(XbbConstant.AND).append("hasAll(" + XbbConstant.JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "'), " + "['\"" + value + "\"'])").append(XbbConstant.SPACE);
                                stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(['\"" + value + "\"'])").append(" = ").append(XbbConstant.LENGTH + "(" + XbbConstant.JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ")");
                            }*/
                        }
                    } else {
                        stringBuffer.append(XbbConstant.AND).append("has(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "'), " + "'" + valList + "')").append(XbbConstant.SPACE);
                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + valList + ")").append(" = ").append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,' " + attr + "')'" + ")");
                    }
                }
                break;
            case IN:
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_MULTI.getType(), fieldType)){
                        StringBuilder s = new StringBuilder();
                        if (valList.size() > 0) {
                            if (attr.contains(StringConstant.POINT)) {
                                String[] attrArray = attr.split("\\.");
                                String attr1;
                                String subForm = attrArray[0];
                                if (StringUtils.isNotEmpty(subForm) && subForm.indexOf("_") != -1) {
                                    if (isNeedRelationSubFormTable(businessType, subForm)) {
                                        attr1 = JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[1] + "')";
                                        s.append("hasAny(").append(attr1)
                                                .append(", ");
                                    } else {
                                        attr1 = attrArray[1];
                                        String arrayRaw = "arrayJoin(" +
                                                JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[0] + "'))";
                                        s.append("hasAny(").append(JSON_EXTRACT_ARRAY_RAW).append("(" + arrayRaw + ",'")
                                                .append(attr1).append("'), ");
                                    }
                                }
                            } else {
                                s.append("hasAny(").append(JSON_EXTRACT_ARRAY_RAW).append("(`data`,'").append(attr)
                                        .append("'), ");
                            }
                            s.append(tempList).append(")");
                        }
                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.SPACE).append(s).append(XbbConstant.SPACE);
                        break;
                    }
                    /*String s = getExtractFuntion(fieldType, value);
                    attr = getStringWithFunN(s,attr);*/
                    attr = getFunctionAttr(attr, fieldType, value, null, businessType, stringBuffer);
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" IN ").append(valList);
                break;
            case NOIN:
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    /*String s = getExtractFuntion(fieldType, value);
                    attr = getStringWithFunN(s,attr);*/
                    attr = getFunctionAttr(attr, fieldType, value, null, businessType, stringBuffer);
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" NOT IN ").append(valList);
                break;
            case GREATEREQUAL:
                //TODO GREATEREQUAL和GREATERTHAN为什么不一样
                if (Objects.isNull(value) || value.toString().isEmpty()) {
                    return;
                }
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                        /*if (attr.contains(StringConstant.POINT)) {
                            String[] attrArray = attr.split("\\.");
                            //attr = attrArray[1];
                            String array_raw = "arrayJoin("+JSON_EXTRACT_ARRAY_RAW+ "(data,'" + attrArray[0] + "'))";
                            for (int i = 1; i < attrArray.length; i++) {
                                //attr  = getExtractFuntion(fieldType,attr) + "("+array_raw+",'" + attr + "')";
                                attr = attrArray[i];
                                attr  = getExtractFuntion(fieldType,attr) + "("+array_raw+",'" + attr + "')";

                            }

                            //JSONExtractInt(arrayJoin(JSONExtractArrayRaw(data,'subForm_2')),'text_1')
                        }else {
                            attr = XbbConstant.JSON_EXTRACT_INT + "(`data`,'" + attr + "')";
                        }*/
                    attr = getFunctionAttr(attr, fieldType, value, XbbConstant.JSON_EXTRACT_DOUBLE, businessType, stringBuffer);
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" >= ").append(value);
                break;
            case GREATERTHAN:
                if (Objects.isNull(value) || value.toString().isEmpty()) {
                    return;
                }
                greaterSql(condition, attr, fieldType, stringBuffer, " > ", corpid, businessType);
                break;
            case LESSEQUAL:
                if (Objects.isNull(value) || value.toString().isEmpty()) {
                    return;
                }
                greaterSql(condition, attr, fieldType, stringBuffer, " <= ", corpid, businessType);
                break;
            case LESSTHAN:
                if (Objects.isNull(value) || value.toString().isEmpty()) {
                    return;
                }
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    //attr = XbbConstant.JSON_EXTRACT_DOUBLE + "(`data`,'" + attr + "')";
                    attr = getFunctionAttr(attr, fieldType, value, XbbConstant.JSON_EXTRACT_DOUBLE, businessType, stringBuffer);
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" < ").append(value);
                break;
            case RANGE:
                if ((Objects.isNull(value) || value.toString().isEmpty())
                        || (Objects.isNull(secondVal) || secondVal.toString().isEmpty())) {
                    return;
                }
                if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                    //attr = XbbConstant.JSON_EXTRACT_INT + "(`data`,'" + attr + "')";
                    attr = getFunctionAttr(attr, fieldType, value, XbbConstant.JSON_EXTRACT_DOUBLE, businessType, stringBuffer);
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" >= ").append(value);
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" < ").append(secondVal);
                break;
            case NORANGE:
                if ((Objects.isNull(value) || value.toString().isEmpty())
                        || (Objects.isNull(secondVal) || secondVal.toString().isEmpty())) {
                    return;
                }
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" < ").append(value);
                stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(" >= ").append(secondVal);
                break;
            default:
                break;
        }
    }

    private void handlerMainSubForm(StringBuffer stringBuffer, String noEmptyStr, String notEqual, Object s2) {
        noEmptyStr = String.format(noEmptyStr, notEqual, s2);
        stringBuffer.append(XbbConstant.AND).append(noEmptyStr);
        return;
    }

    /**
     * @param attr
     * @param stringBuffer
     * @param operator
     * @param businessType
     * @return void
     * @throws
     * @Description 处理子表单空、非空
     * @Date 17:01 2022/1/11
     **/

    private static void handlerSubformComboEmpty(String attr, StringBuffer stringBuffer, String operator, Integer businessType) {
        if (StringUtils.isEmpty(operator)) {
            return;
        }
        if (StringUtils.isNotEmpty(attr) && attr.contains(StringConstant.POINT)) {
            String[] attrArray = attr.split("\\.");
            String subForm = attrArray[0];
            if (StringUtils.isNotEmpty(subForm) && subForm.indexOf("_") != -1) {
                if (isNeedRelationSubFormTable(businessType, subForm)) {
                    String attrStr = " attr = '" + subForm + "' AND ";
                    if (null != stringBuffer && stringBuffer.indexOf(attrStr) != -1) {
                        attrStr = "";
                    }
                    attr = attrStr + XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attrArray[1] + "')" + ") " + operator + " 0 ";
                    stringBuffer.append(XbbConstant.AND).append(attr);
                } else {
                    stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ") " + operator + " 0 ");
                }
            }
        } else {
            stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + JSON_EXTRACT_ARRAY_RAW + "(`data`,'" + attr + "')" + ") " + operator + " 0 ");
        }
    }

    /**
     * @param attr
     * @param fieldType
     * @param value
     * @param functionName
     * @param businessType
     * @param stringBuffer
     * @return java.lang.String
     * @throws
     * @Description 添加子表单处理逻辑
     * @Date 16:56 2022/1/11
     * @Param
     **/

    private static String getFunctionAttr(String attr, Integer fieldType, Object value, String functionName, Integer businessType, StringBuffer stringBuffer) {
        if (StringUtils.isNotEmpty(attr) && attr.contains(StringConstant.POINT)) {
            String[] attrArray = attr.split("\\.");
            String subForm = attrArray[0];
            if (StringUtils.isNotEmpty(subForm) && subForm.indexOf("_") != -1) {
                if (isNeedRelationSubFormTable(businessType, subForm)) {
                    String attrStr = " attr = '" + subForm + "' AND ";
                    if (null != stringBuffer && stringBuffer.indexOf(attrStr) != -1) {
                        attrStr = "";
                    }
                    String extractFuntion = getExtractFuntion(fieldType, value);
                    //attr = attrStr + extractFuntion + "(data,'" + attrArray[1] + "')";
                    attr = String.format("%s%s", attrStr, CommonHelper.getExtractString(extractFuntion, null, attrArray[1]));

                } else {
                    attr = "empty(arrayElement(arrayFilter((x -> " + JSON_EXTRACT + "(x,'" + attrArray[1] + "','"+XbbConstant.STRING_CONSTANT+"')  %s %s), " + JSON_EXTRACT_ARRAY_RAW + "(data,'" + attrArray[0] + "')),1)) = 0";
                    /*String array_raw = "arrayJoin("+JSON_EXTRACT_ARRAY_RAW+ "(data,'" + attrArray[0] + "'))";
                    for (int i = 1; i < attrArray.length; i++) {
                        //attr  = getExtractFuntion(fieldType,attr) + "("+array_raw+",'" + attr + "')";
                        attr = attrArray[i];
                        attr = getExtractFuntion(fieldType,value) + "("+array_raw+",'" + attr + "')";
                    }*/
                }
            }
            //JSONExtractInt(arrayJoin(JSONExtractArrayRaw(data,'subForm_2')),'text_1')
        } else {
            if (StringUtils.isEmpty(functionName)) {
                functionName = getExtractFuntion(fieldType, value);
            }
            if (Objects.equals(XbbRefTypeEnum.CONTRACT_PERFORMANCE.getCode(), businessType)) {
                attr = StringUtil.getDataBaseString(ContractPerformanceEnum.getRealAttr(attr));
            } else {
                attr = getStringWithFunN(functionName, attr);
            }
        }
        return attr;
    }

    /**
     * @return java.lang.String
     * @throws
     * @Description 根据函数名、属性名生成包装sql段
     * @Date 10:01 2021/12/14
     * @Param [attr, funName]
     **/

    private static String getStringWithFunN(String funName, String attr) {
        if (StringUtils.equals(JSON_EXTRACT,funName)) {
            attr = MessageFormat.format("{0}(`data`,''{1}'',''{2}'') ", funName, attr,STRING_CONSTANT);
        }else {
            attr = MessageFormat.format("{0}(`data`,''{1}'') ", funName, attr);
        }
        return attr;
    }

    /**
     * @return java.lang.String
     * @throws
     * @Description 根据filedType。value值确定抽取函数名
     * @Date 19:34 2021/12/13
     * @Param [fieldType, value]
     **/

    public static String getExtractFuntion(Integer fieldType, Object value) {
        String funName = JSON_EXTRACT;
        FieldTypeEnum fieldTypeE = FieldTypeEnum.getFieldTypeEnum(fieldType);
        if (fieldTypeE != null) {
            String esalias = fieldTypeE.getEsalias();
            if (StringUtils.equals(esalias, EsAliasEnum.NUM.getEsAlias())) {
                funName = getNumExtractFuntion(value);
            } else if (StringUtils.equals(esalias, EsAliasEnum.LONG.getEsAlias()) ||
                    StringUtils.equals(esalias, EsAliasEnum.DATE.getEsAlias())) {
                funName = XbbConstant.JSON_EXTRACT_BIGINT;
            } else if (StringUtils.equals(esalias, EsAliasEnum.ARRAY.getEsAlias())) {
                //todo 特殊类型用arrayrow
                funName = JSON_EXTRACT_RAW;
            } else if (Objects.equals(FieldTypeEnum.DEPT.getType(), fieldType)) {
                funName = XbbConstant.JSON_EXTRACT_BIGINT;
            }
        }
        return funName;

    }


    public static String getNumExtractFuntion(Object value) {
        String funName = XbbConstant.JSON_EXTRACT_DOUBLE;
        if (value instanceof Integer) {
            funName = XbbConstant.JSON_EXTRACT_BIGINT;
        } /*else if (value instanceof String) {
                funName = XbbConstant.JSON_EXTRACT_STRING;
            }*/
        return funName;
    }

    private static void greaterSql(ConditionsEntityExt condition, String attr, Integer fieldType, StringBuffer stringBuffer, String logicalSymbol, String corpid, Integer businessType) {
        Object value = condition.getValue().get(0);
        //子表单日期过滤需要特殊处理
        if ((Objects.equals(FieldTypeEnum.NUM.getType(), condition.getFieldType()) && RegexUtil.isNumber(value.toString())) || isNeedRelationSubFormTable(businessType, attr)) {
            /*if (value.toString().contains(".")) {
                value = Double.valueOf(value.toString());
                if (EsUtil.setInData(fieldType)) {
                    attr = XbbConstant.JSON_EXTRACT_DOUBLE + "(`data`,'" + attr + "')";
                }
            } else {
                value = Long.valueOf(value.toString());
                if (EsUtil.setInData(fieldType)) {
                    attr = XbbConstant.JSON_EXTRACT_DOUBLE + "(`data`,'" + attr + "')";
                }
            }*/
            if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                //attr = XbbConstant.JSON_EXTRACT_DOUBLE + "(`data`,'" + attr + "')";
                attr = getFunctionAttr(attr, fieldType, value, XbbConstant.JSON_EXTRACT_DOUBLE, businessType, stringBuffer);
            }
            stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(logicalSymbol).append(value);
        } else {//todo 非数字要抛异常
            long time = Long.parseLong(condition.getValue().get(0).toString());
            FieldTypeEnum dateFieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(condition.getFieldType());
            if (Objects.nonNull(dateFieldTypeEnum) && Objects.equals(dateFieldTypeEnum.getEsalias(), FieldTypeEnum.DATETIME.getEsalias())) {
                //time = DateTimeUtil.getTodayInt(time) + TimeConstant.SECONDS_PER_DAY - 1;
                // 小于等于需要到该分钟的最后一秒
               time = time + TimeConstant.SECONDS_PER_MINUTE - 1;
            }
            if (EsUtil.setInData(fieldType) && !EsUtil.specialOutData(businessType, fieldType)) {
                attr = XbbConstant.JSON_EXTRACT_INT + "(`data`,'" + attr + "')";
            }
            stringBuffer.append(XbbConstant.AND).append(attr).append(XbbConstant.SPACE).append(logicalSymbol).append(time);
        }
    }

    private void biAddressConditionSymbolChoose(String corpid, Map<String, StringBuffer> fliterMap, ConditionEnum conditionEnum, ConditionsEntityExt condition, boolean isSingle) {
        String attr = condition.getAttr();
        if (!isSingle) {
            attr = Objects.isNull(condition.getOriginalAttr()) ? attr : condition.getOriginalAttr();
        }
        List<Object> values = condition.getValue();
        Long formId = condition.getFormId();
        StringBuffer stringBuffer = fliterMap.get(formId.toString());
        //生成初始的sql拼装语句
        stringBuffer = initSqlString(corpid, formId, condition.getBusinessType(), fliterMap, stringBuffer, attr);
        String province = null;
        String city = null;
        String district = null;
        if (values != null) {
            province = values.size() > 0 ? values.get(0).toString() : null;
            city = values.size() > 1 ? values.get(1).toString() : null;
            district = values.size() > 2 ? values.get(2).toString() : null;
        }
        boolean containsAddress = attr.contains(BusinessConstant.PROVINCE) || attr.contains(BusinessConstant.CITY) || attr.contains(BusinessConstant.DISTRICT);
        switch (conditionEnum) {
            case EQUAL:
                // and  JSONExtractString(JSONExtractRaw(data,'address_1'),'city') ='杭州市'
                addressSql(attr, stringBuffer, province, city, district, " = ", XbbConstant.AND, containsAddress);
                break;
            case NOEQUAL:
                //TODO   根据等于修改
                addressSql(attr, stringBuffer, province, city, district, " != ", XbbConstant.AND, containsAddress);
                break;
            case EMPTY:
      /*          BoolQueryBuilder boolQuery = boolQuery();
                //兼容穿透查询
                if (Objects.equals(condition.getPenetrateFlag(), BasicConstant.ONE) || containsAddress) {
                    boolQuery.should(boolQuery().filter(termQuery(attr + keyword, "")));
                } else {
                    boolQuery.should(boolQuery().filter(termQuery(attr + StringConstant.POINT + BusinessConstant.PROVINCE + keyword, "")));
                }
                boolQuery.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);*/
//                boolQueryBuilder.must(boolQuery);
                stringBuffer.append(XbbConstant.AND).append(XbbConstant.SPACE).append(XbbConstant.L_P);
                //address_为空
                //PROVINCE为空
                String addressKey = attr;
                String provinceKey = BusinessConstant.PROVINCE;
                if (containsAddress) {
                    String[] attrArray = attr.split("\\.");
                    addressKey = attrArray[0];
                    provinceKey = attrArray[1];
                }
                stringBuffer.append(XbbConstant.SPACE)
                        .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(addressKey).append("'").append(")").append(",").append("'").append(provinceKey).append("'").append(")").append(" = ")
                        .append("'").append("'");
                stringBuffer.append(XbbConstant.OR).append(XbbConstant.SPACE)
                        .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(addressKey).append("'").append(")").append(",").append("'").append("address").append("'").append(")").append(" = ")
                        .append("'").append("'");
                stringBuffer.append(XbbConstant.SPACE).append(XbbConstant.R_P);
                break;
            case NOEMPTY:
                //TODO
               /* if (Objects.equals(condition.getPenetrateFlag(), BasicConstant.ONE) || containsAddress) {
                    boolQueryBuilder.filter(boolQuery().mustNot(termQuery(attr + keyword,"")));
                    boolQueryBuilder.filter(boolQuery().must(existsQuery(attr + keyword)));
                } else {
                    boolQueryBuilder.filter(boolQuery().mustNot(termQuery(attr + StringConstant.POINT + BusinessConstant.PROVINCE + keyword,"")));
                    boolQueryBuilder.filter(boolQuery().must(existsQuery(attr + StringConstant.POINT + BusinessConstant.PROVINCE + keyword)));
                }*/
                stringBuffer.append(XbbConstant.AND).append(XbbConstant.SPACE).append(XbbConstant.L_P);
                //address_不为空
                //PROVINCE不为空
                String addresskey = attr;
                String provincekey = BusinessConstant.PROVINCE;
                if (containsAddress) {
                    String[] attrArray = attr.split("\\.");
                    addresskey = attrArray[0];
                    provincekey = attrArray[1];
                }
                stringBuffer.append(XbbConstant.SPACE)
                        .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(addresskey).append("'").append(")").append(",").append("'").append(provincekey).append("'").append(")").append(" != ")
                        .append("'").append("'");
                stringBuffer.append(XbbConstant.OR).append(XbbConstant.SPACE)
                        .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(addresskey).append("'").append(")").append(",").append("'").append("address").append("'").append(")").append(" != ")
                        .append("'").append("'");
                stringBuffer.append(XbbConstant.SPACE).append(XbbConstant.R_P);
                break;
            case LIKE:
                BoolQueryBuilder likeBoolQuery = boolQuery();
                if (province != null) {
                    if (Objects.equals(condition.getPenetrateFlag(), BasicConstant.ONE) || containsAddress) {
                        //TODO
//                        likeBoolQuery.should(matchPhraseQuery(attr, province));
                    } else {
                /*        likeBoolQuery.should(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.PROVINCE, province));
                        likeBoolQuery.should(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.CITY, province));
                        likeBoolQuery.should(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.DISTRICT, province));
                        likeBoolQuery.should(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.ADDRESS, province));*/
                        addressSql(attr, stringBuffer, province, province, province, " like ", XbbConstant.OR, containsAddress);
                        stringBuffer.append(XbbConstant.OR).append(XbbConstant.SPACE)
                                .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append(",").append("'").append(BusinessConstant.ADDRESS).append("'").append(")").append(" like ")
                                .append("'").append(province).append("'");
                    }
                }
                likeBoolQuery.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
//                boolQueryBuilder.filter(likeBoolQuery);
                break;
            case NOLIKE:
                BoolQueryBuilder noLikeBoolQuery = boolQuery();
                if (province != null) {
                    if (Objects.equals(condition.getPenetrateFlag(), BasicConstant.ONE) || containsAddress) {
                        //TODO
//                        noLikeBoolQuery.must(boolQuery().mustNot(matchPhraseQuery(attr, province)));
                    } else {
                        /*noLikeBoolQuery.must(boolQuery().mustNot(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.PROVINCE, province)));
                        noLikeBoolQuery.must(boolQuery().mustNot(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.CITY, province)));
                        noLikeBoolQuery.must(boolQuery().mustNot(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.DISTRICT, province)));*/
//                        noLikeBoolQuery.must(boolQuery().mustNot(matchPhraseQuery(attr + StringConstant.POINT + BusinessConstant.ADDRESS, province)));
                        //不等于前端把值放在了province上
                        addressSql(attr, stringBuffer, province, province, province, " not like ", XbbConstant.AND, containsAddress);
                        stringBuffer.append(XbbConstant.AND).append(XbbConstant.SPACE)
                                .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append(",").append("'").append(BusinessConstant.ADDRESS).append("'").append(")").append(" not like ")
                                .append("'").append(province).append("'");
                    }
                }
                break;
            default:
                break;
        }
    }

    private static void addressSql(String attr, StringBuffer stringBuffer, String province, String city, String district, String logicalSymbol, String connector, boolean containsAddress) {
        //兼容穿透查询
        if (containsAddress) {
            //值放在了第一个位置
            if (province != null) {
                String[] attrKey = attr.split("\\.");
                stringBuffer.append(connector).append(XbbConstant.SPACE)
                        .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attrKey[0]).append("'").append(")").append(",").append("'").append(attrKey[1]).append("'").append(")").append(logicalSymbol)
                        .append("'").append(province).append("'");
            }
        } else {
            if (province != null) {
                stringBuffer.append(connector).append(XbbConstant.SPACE)
                        .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append(",").append("'").append(BusinessConstant.PROVINCE).append("'").append(")").append(logicalSymbol)
                        .append("'").append(province).append("'");
                if (city != null) {
                    stringBuffer.append(connector).append(XbbConstant.SPACE)
                            .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append(",").append("'").append(BusinessConstant.CITY).append("'").append(")").append(logicalSymbol)
                            .append("'").append(city).append("'");
                    if (district != null) {
                        stringBuffer.append(connector).append(XbbConstant.SPACE)
                                .append(JSON_EXTRACT_STRING).append("(").append(JSON_EXTRACT_RAW).append("(data," + "'").append(attr).append("'").append(")").append(",").append("'").append(BusinessConstant.DISTRICT).append("'").append(")").append(logicalSymbol)
                                .append("'").append(district).append("'");
                    }
                }
            }
        }
    }


    /**
     * 生成初始的sql拼装语句
     *
     * @param corpid
     * @param formId
     * @param businessType
     * @param filterMap
     * @param stringBuffer
     */
    private StringBuffer initSqlString(String corpid, Long formId, Integer businessType, Map<String, StringBuffer> filterMap,
                                       StringBuffer stringBuffer, String attr) {
        if (stringBuffer == null) {
            stringBuffer = new StringBuffer();
            XbbTableRefEnum xbbTableRefEnum = XbbTableRefEnum.getByCode(businessType);
            Long mainFormId = formId;
            PaasFormRefEntity paasFormRefEntity = null;
            if (BIProductReformEnum.getProductSubBusList().contains(businessType)) {
                paasFormRefEntity = paasFormRefModel.getMainFormIdByFormId(formId, corpid);
                if (!Objects.isNull(paasFormRefEntity)) {
                    mainFormId = paasFormRefEntity.getMainFormId();
                }
            }
            String tableName = xbbTableRefEnum.getTableName();
            stringBuffer.append(" from ").append(tableName).append(" prewhere ")
                    .append("corpid = ").append("'").append(corpid).append("'").append(XbbConstant.SPACE);
            // 这些业务里没有formId，过滤掉
            boolean isRefund = Objects.equals(businessType, XbbRefTypeEnum.CONTRACT_PRODUCT.getCode()) && paasFormRefEntity != null && Objects.equals(paasFormRefEntity.getType(), XbbRefTypeEnum.REFUND.getCode());
            if (mainFormId != null) {
                if (!isRefund
                        && !Objects.equals(businessType, XbbRefTypeEnum.QUOTATION_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.SUPPLIER_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.PURCHASE_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.RETURNEDPURCHASE_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.BOM_BILL_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.PRODUCTION_ORDER_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.INVENTORY_PRODUCT.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.CONTRACT_PERFORMANCE.getCode())
                        && !Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER_V2_NODE_LOG_INFO.getCode())) {
                    stringBuffer.append(XbbConstant.AND).append(" form_id = ").append(mainFormId).append(XbbConstant.SPACE);
                } else if (Objects.equals(businessType, XbbRefTypeEnum.PRODUCTION_ORDER_PRODUCT.getCode()) 
                        || Objects.equals(businessType, XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode()) 
                        || Objects.equals(businessType, XbbRefTypeEnum.BOM_BILL_PRODUCT.getCode())
                        || Objects.equals(businessType, XbbRefTypeEnum.CONTRACT_PRODUCT.getCode())
                        || Objects.equals(businessType, XbbRefTypeEnum.INSTOCK_PRODUCT.getCode())
                        || Objects.equals(businessType, XbbRefTypeEnum.OUTSTOCK_PRODUCT.getCode())
                ) {
                    if (Objects.nonNull(paasFormRefEntity) && Objects.nonNull(paasFormRefEntity.getType())){
                        stringBuffer.append(XbbConstant.AND).append(" type = ").append(paasFormRefEntity.getType()).append(XbbConstant.SPACE);
                    }
                }
            }
            // 退货退款产品和合同产品存一起，但form_id只存合同的，很迷，目前退货退款是单模板，用type做区分了，若后期开多模板，自求多福吧
            if (paasFormRefEntity != null
                    && (isRefund || Objects.equals(businessType, XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode()) || Objects.equals(businessType, XbbRefTypeEnum.BOM_BILL_PRODUCT.getCode()))) {
                stringBuffer.append(XbbConstant.AND).append(" type = ").append(paasFormRefEntity.getType()).append(XbbConstant.SPACE);
            }
            stringBuffer.append(XbbConstant.GROUP_ID).append(" having del = 0 ");
            // 当需要拿产品字段去统计的时候，拿的是子产品
            if (Objects.equals(XbbRefTypeEnum.PRODUCT.getCode(), businessType)) {
                stringBuffer.append(XbbConstant.AND).append(XbbConstant.JSON_EXTRACT_DOUBLE).append(XbbConstant.L_P)
                        .append(XbbConstant.DATA).append(SymbolConstant.COMMA_ENGLISH).append(XbbConstant.SINGLE_QUOTES)
                        .append(ProductEnum.PARENT_ID.getAttr()).append(XbbConstant.SINGLE_QUOTES)
                        .append(XbbConstant.R_P).append(XbbConstant.G_T).append(BasicConstant.ZERO);
            }
            // 审批流程默认值
            handleFlowStatus(businessType, stringBuffer);
            filterMap.put(formId.toString(), stringBuffer);
        } else {
            if (StringUtils.isNotEmpty(attr) && attr.contains(StringConstant.POINT) && !Objects.isNull(businessType)) {
                String subFormTableName = subFormHashMap.get(businessType);
                if (StringUtils.isEmpty(subFormTableName)) {
                    subFormTableName = XbbTableRefEnum.getSubFormNameByParent(businessType);
                    subFormHashMap.putIfAbsent(businessType, subFormTableName);
                }
                if (StringUtils.isNotEmpty(subFormTableName)) {
                    String subFormIn = "SELECT data_id from " + subFormTableName + " prewhere corpid = '" + corpid + "' and del =0 ";
                    String[] attrArray = attr.split("\\.");
                    String subForm = attrArray[0];
                    if (StringUtil.isEmpty(subForm)) {
                        return stringBuffer;
                    }
                    int indexOf = stringBuffer.indexOf(subFormTableName);
                    boolean needRelationSubFormTable = isNeedRelationSubFormTable(businessType, subForm);
                    if (indexOf == -1) {
                        currentSubFormName = subForm;
                        if (needRelationSubFormTable) {
                            String subFormSql = " AND id in (SELECT data_id from " + subFormTableName + "  where corpid ='" + corpid + "' " +
                                    " and del =0 ";
                            stringBuffer.append(subFormSql);
                        }
                    }
                    if (indexOf != -1) {
                        if (needRelationSubFormTable) {
                            if (!StringUtils.equals(currentSubFormName, subForm)) {
                                currentSubFormName = subForm;
                                //阿里云版ck不支持intersect，用in代替
                                //stringBuffer.append(" intersect ").append(subFormIn);
                                stringBuffer.append(" and  data_id in ( ").append(subFormIn);
                            }
                        }
                    }
                }
            }
        }
        return stringBuffer;
    }

    /**
     * 审批默认条件
     *
     * @param businessType
     * @param stringBuffer
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2022/2/15 19:14
     * @version 1.0
     */
    private static void handleFlowStatus(Integer businessType, StringBuffer stringBuffer) {
        if (!Objects.equals(businessType, XbbRefTypeEnum.CONTRACT_PERFORMANCE.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.CONTRACT_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.SALES_OPPORTUNITY_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.QUOTATION_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.SUPPLIER_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.PURCHASE_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.RETURNEDPURCHASE_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.BOM_BILL_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.PRODUCTION_ORDER_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.INVENTORY_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.TRANSFER_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.INSTOCK_PRODUCT.getCode())
                && !Objects.equals(businessType, XbbRefTypeEnum.OUTSTOCK_PRODUCT.getCode())
        ) {
            String flowStatusAttr = StringUtil.getDataBaseString(BiEsAliasEnum.FLOWSTATUS.getEsAlias());
            stringBuffer.append(XbbConstant.SPACE)
                    .append(XbbConstant.AND).append(XbbConstant.SPACE)
                    .append(flowStatusAttr)
                    .append(XbbConstant.SPACE)
                    .append(ConditionEnum.IN.getReplaceSymbol()).append(XbbConstant.SPACE)
                    .append(Stream.of(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType()).collect(Collectors.toList()));
        }
    }

    /**
     * @param businessType
     * @return void
     * @throws
     * @Description 是否需要关联子表单
     * @Date 10:55 2022/1/11
     **/

    private static boolean isNeedRelationSubFormTable(Integer businessType, String attr) {
        if (StringUtils.isEmpty(attr) || !attr.startsWith("subForm") || Objects.isNull(businessType)) {
            return false;
        }
        if (Objects.equals(XbbRefTypeEnum.CLUE.getCode(), businessType)
                || Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), businessType) || Objects.equals(XbbRefTypeEnum.SUPPLIER.getCode(), businessType) ||
                Objects.equals(XbbRefTypeEnum.SUPPLIER_CONTACT.getCode(), businessType)
                || Objects.equals(XbbRefTypeEnum.CONTACT.getCode(), businessType) || Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), businessType)) {
            if (StringUtils.equals("subForm_1", attr)) {
                return false;
            } else {
                return true;
            }
        }
        //subForm_2特殊处理
        if (StringUtils.equals("subForm_2", attr) && Objects.equals(XbbRefTypeEnum.WORK_REPORT.getCode(), businessType)) {
            return false;
        }
        //subForm_3特殊处理
        if (StringUtils.equals("subForm_3", attr) && Objects.equals(XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode(), businessType)) {
            return false;
        }
        return true;
    }


    /**
     * 拼装join条件
     *  @param tbJson          从表
     * @param sqlBuffer
     * @param linkAttrCopy    主表的关联字段
     * @param driverTableName 主表名
     * @param tableAlias      从表名
     * @param inData          主表关联字段是否在data里
     * @param inDataFollow    从表关联字段是否在data里
     * @param allPermission  右侧是否选择了全部数据权限
     */
    public void appendJoinSql(int isSingleRef, JSONObject tbJson, StringBuffer sqlBuffer, String linkAttrCopy,
                              String driverTableName, String tableAlias, Integer inData, Integer inDataFollow, String corpid, Map<String, StringBuffer> fliterMap, boolean isMaxPermission, boolean allPermission) {
        //主表关联字段
        if (Objects.equals("dataId", linkAttrCopy)) {
            linkAttrCopy = linkAttrCopy.replace("dataId", "id");
        }
        //从表关联字段
        String linkAttrCopyFollow = tbJson.getString("linkAttrCopy");
        if (Objects.equals("dataId", linkAttrCopyFollow)) {
            linkAttrCopyFollow = linkAttrCopyFollow.replace("dataId", "id");
        }
        if (Objects.equals(tableAlias, XbbTableRefEnum.REFUND.getTableName())) {
            linkAttrCopyFollow = RefundEnum.RED_CONTRACT_ID.getAttr();
            inDataFollow = 1;
        }
        //驼峰转下划线
        linkAttrCopy = StringUtil.getDataBaseString(linkAttrCopy);
        linkAttrCopyFollow = StringUtil.getDataBaseString(linkAttrCopyFollow);
        if (StringUtils.equals(XbbTableRefEnum.CONTRACT_PERFORMANCE.getTableName(), tableAlias)) {
            inDataFollow = 0;
            if (!linkAttrCopyFollow.equals(StringConstant.SAAS_LINK_BUSINESS_ID)) {
                linkAttrCopyFollow = StringUtil.getDataBaseString(ContractPerformanceEnum.getRealAttr(linkAttrCopyFollow));
            }
        }
        if (Objects.equals(driverTableName, XbbTableRefEnum.WORK_ORDER_V2_NODE_LOG_INFO.getTableName()) && !Objects.equals(linkAttrCopy, StringConstant.WORK_ORDER_ID)){
            appendJoinOnSql(isSingleRef, sqlBuffer, linkAttrCopy, XbbTableRefEnum.WORK_ORDER_V2.getTableName(), linkAttrCopyFollow, inDataFollow);
        }else if (Objects.equals(0, inData)) {
            sqlBuffer.append(driverTableName).append(".").append(renameUpdateTime(linkAttrCopy));
        } else {
            appendJoinOnSql(isSingleRef, sqlBuffer, linkAttrCopy, driverTableName, linkAttrCopyFollow, inDataFollow);
        }
        sqlBuffer.append(" = ");
        if (Objects.equals(0, inDataFollow)) {
            sqlBuffer.append(tableAlias).append(".").append(renameUpdateTime(linkAttrCopyFollow));
        } else {
            appendJoinOnSql(isSingleRef, sqlBuffer, linkAttrCopyFollow, tableAlias, linkAttrCopy, inData);
        }
        //团队
        /*if (Objects.equals(tbJson.getInteger("saasMark"), SaasMarkEnum.SAAS.getCode())) {
        }*/
        Integer slvBusinessType = tbJson.getInteger("businessType");
        String teamName = getTeamNameByBusinessType(slvBusinessType);
        StringBuffer condition = fliterMap.get(tbJson.getLong("formId") + "_" + teamName);
        boolean isPublicFlag = false;
        if (StringUtils.equals(tableAlias, XbbTableRefEnum.CUSTOMER_MANAGEMENT.getTableName())) {
            isPublicFlag = ChartUtil.isPublicFlag(tbJson);
        }
        Boolean[] booleans = {isMaxPermission, isPublicFlag,allPermission};
        if (isNeedTeam(booleans, sqlBuffer, condition, teamName)) {
            String teamNameAlias = teamName;
            if (!Objects.equals(XbbTableRefEnum.getByCode(slvBusinessType), tableAlias)) {
                teamNameAlias += tableAlias.substring(XbbTableRefEnum.getByCode(slvBusinessType).getTableName().length());
            }
            appendTeamJoinSql(sqlBuffer, tableAlias, tbJson.getLong("formId"), teamName, corpid, fliterMap, isMaxPermission, teamNameAlias);
        }
    }

    /**
     * @return java.lang.String
     * @author gzt
     * @Description 添加团队名称Map缓存
     * @Date 14:57 2022/2/17
     **/

    private static String getTeamNameByBusinessType(Integer businessType) {
        String teamName = teamUserHashMap.get(businessType);
        if (StringUtils.isEmpty(teamName) && !Objects.isNull(businessType)) {
            teamName = XbbTableRefEnum.getTeamNameByParent(businessType);
            teamUserHashMap.putIfAbsent(businessType, teamName);
        }
        return teamName;
    }

    /**
     * @return boolean
     * @throws
     * @Description 判断是否需要append团队
     * @Date 14:30 2021/12/29
     * @Param [booleans, i, condition, teamName]
     **/

    private boolean isNeedTeam(Boolean[] booleans, StringBuffer stringBuffer, StringBuffer condition, String teamName) {
        if (StringUtils.isNotEmpty(teamName) && null != booleans && StringUtils.isNotEmpty(stringBuffer)) {
            if (Objects.equals(true, booleans[1])) {
                return false;
            }
            int indexOf = stringBuffer.indexOf(teamName);
            //全部数据权限，且没有筛选的时候 不关联团队表
            if((booleans[2] && indexOf == -1) &&  condition == null){
                return false;
            }
            return (!booleans[0] && indexOf == -1) || indexOf != -1 || condition != null;
        } else {
            return false;
        }
    }

    /**
     * @param sqlBuffer
     * @param linkAttrCopy       自己表的关联字段
     * @param tableAlias         表名
     * @param linkAttrCopyFollow 对应表的关联字段
     * @param inDataFollow       对应表是否在data中
     */
    private void appendJoinOnSql(int isSingleRef, StringBuffer sqlBuffer, String linkAttrCopy, String tableAlias, String linkAttrCopyFollow, Integer inDataFollow) {
        boolean flag = false;
        String funName = JSON_EXTRACT;
        if (linkAttrCopy.contains("num")) {
            //如果对等字段包含以下字段
            if (linkAttrCopyFollow.contains("id") || linkAttrCopyFollow.contains("date") || linkAttrCopyFollow.contains("Time")) {
                funName = XbbConstant.JSON_EXTRACT_BIGINT;
            } else {
                funName = XbbConstant.JSON_EXTRACT_DOUBLE;
            }
        } else if (linkAttrCopy.contains("date")) {
            funName = XbbConstant.JSON_EXTRACT_BIGINT;
        } else {
            if (Objects.equals(0, inDataFollow) && !(Objects.equals("corpid", linkAttrCopyFollow) || Objects.equals("serial_no", linkAttrCopyFollow) || Objects.equals("owner_id", linkAttrCopyFollow) || Objects.equals("creator_id", linkAttrCopyFollow))) {
                flag = true;
                //toInt64OrZero(JSONExtractString(tb_saas_contract.data, 'text_2'))
                if (linkAttrCopyFollow.contains("id") || linkAttrCopyFollow.contains("date") || linkAttrCopyFollow.contains("Time")) {
                    //sqlBuffer.append(XbbConstant.TO_INT_64_OR_ZERO).append("(").append(XbbConstant.JSON_EXTRACT_STRING);
                    if (isSingleRef == 0) {
                        sqlBuffer.append(XbbConstant.TO_INT_64_OR_ZERO).append(XbbConstant.L_P);
                        if (Objects.nonNull(tableAlias) && (StringUtils.contains(tableAlias,XbbTableRefEnum.PAY_SHEET.getTableName()) ||
                                StringUtils.contains(tableAlias,XbbTableRefEnum.PAYMENT_SHEET.getTableName()))){
                            sqlBuffer.append("replaceRegexpAll(").append("replaceRegexpAll("+CommonHelper.getExtractString(funName,tableAlias,linkAttrCopy)+"," +
                                    "  '(\\\\[)(.*)(\\\\])','\\\\2')").append("," +
                                    "  '(\\\")(.*)(\\\")','\\\\2')").append(XbbConstant.R_P);
                        }else {
                            sqlBuffer.append(CommonHelper.getExtractString(funName,tableAlias,linkAttrCopy)).append(XbbConstant.R_P);
                        }
                    } else {
                        sqlBuffer.append(XbbConstant.L_P);
                        funName = XbbConstant.JSON_EXTRACT_INT;
                    }
                } else {
                    sqlBuffer.append(XbbConstant.L_P);
                    funName = XbbConstant.JSON_EXTRACT_DOUBLE;
                }
                if (!StringUtils.equals(JSON_EXTRACT,funName)) {
                    sqlBuffer.append(CommonHelper.getExtractString(funName,tableAlias,linkAttrCopy)).append(XbbConstant.R_P);
                }
            } else {
                funName = XbbConstant.JSON_EXTRACT;
            }
        }
        if (!flag) {
            sqlBuffer.append(CommonHelper.getExtractString(funName,tableAlias,linkAttrCopy));
        }
    }

    public void appendTeamJoinSql(StringBuffer stringBuffer, String driverTableName, Long formId, String teamName, String corpid, Map<String, StringBuffer> fliterMap, boolean isMaxPermission) {
        appendTeamJoinSql(stringBuffer, driverTableName, formId, teamName, corpid, fliterMap, isMaxPermission, teamName);
    }

    public void appendTeamJoinSql(StringBuffer stringBuffer, String driverTableName, Long formId, String teamName, String corpid, Map<String, StringBuffer> fliterMap, boolean isMaxPermission, String teamNameAlias) {
        if (StringUtil.isNotEmpty(teamName)) {
            boolean emptyFlag = false;
            StringBuffer condition = fliterMap.get(formId + "_" + teamName);
            StringBuffer emptyCondition = fliterMap.get(formId + "_" + teamName + "_" + ConditionEnum.EMPTY.getSymbol());
            if(emptyCondition != null && Objects.equals(emptyCondition.toString(),"true")){
                emptyFlag = true;
            }
            if (isMaxPermission && condition == null) {
                //超管，选择负责人展示join的时候可能团队表没有符合的数据，但是主表的数据还是在列表页展现
                //当选了包含或者等于的时候（只提供这两种筛选） 不能用left_join 要过滤掉没有负责人的
                stringBuffer.append(XbbConstant.LEFT_JOIN);
            }else if(emptyFlag){
                stringBuffer.append(XbbConstant.LEFT_JOIN);
            } else {
                stringBuffer.append(XbbConstant.LEFT_SEMI_JOIN);
            }
            stringBuffer.append("( ");
            if (condition != null) {
                stringBuffer.append("select * from ( ");
            }
            //todo  这三张表需要特殊处理
            String specialTables = MessageFormat.format("{0}{1}{2}}{3}", XbbTableRefEnum.WAREHOUSE_TEAM.getTableName(),
                    XbbTableRefEnum.COMMUNICATE_PLAN_TEAM.getTableName(), XbbTableRefEnum.PRODUCT_TEAM.getTableName(), XbbTableRefEnum.COMPETITOR_TEAM.getTableName());
            //if ("tb_saas_warehouse_usertb_saas_communicate_plan_usertb_saas_product_user".indexOf(teamName)!= -1){
            if (specialTables.contains(teamName)) {
                stringBuffer.append("select * from ").append(teamName).append(" final prewhere corpid = ").append("'")
                        .append(corpid).append("'").append(XbbConstant.SPACE).append("and  del = 0  ");
            } else {
                stringBuffer.append("select ").append("data_id,arraySort(groupArray(if(is_main == 0,user_id,null))) AS ").append(XbbConstant.TEAM_CO)
                        .append(" ,arraySort(groupArray(if(is_main == 1,user_id,null))) AS ").append(XbbConstant.TEAM_MAIN).append(" from ")
                        .append("(SELECT argMax(user_id ,update_time) as user_id ");
                //因为这张表没有 user_name字段
                if (!Objects.equals(teamName, XbbTableRefEnum.RECEIPT_ORDER_TEAM.getTableName())
                        && !(Objects.equals(teamName, XbbTableRefEnum.WORK_ORDER_V2_TEAM.getTableName()))) {
                    stringBuffer.append(",argMax(user_name ,update_time) as user_name");
                }
                stringBuffer.append(" ,argMax(data_id ,update_time) as data_id ,argMax(is_main ,update_time) as is_main" +
                                " ,argMax(del,update_time) as del from ").append(teamName).append(" prewhere corpid = ").append("'")
                        .append(corpid).append("'").append(XbbConstant.SPACE).append(XbbConstant.GROUP_ID).append(" having del = 0 )");
                //.append(XbbConstant.FINAL).append(" prewhere ")
                //stringBuffer.append(" prewhere ")
                //.append("corpid = ").append("'").append(corpid).append("'").append(XbbConstant.SPACE)
                //TODO  客户公海不加del???
                //.append(" del =0 ")
                stringBuffer.append(" GROUP BY ").append("data_id ");
            }
            if (condition != null) {
                stringBuffer.append(" ) where 1 ").append(condition);
            }
            stringBuffer.append(") AS ").append(teamNameAlias)
                    .append(" ON ").append(driverTableName).append(".id = ").append(teamNameAlias).append(".data_id ");
            if(emptyFlag){
                StringBuffer emptySql = fliterMap.get(ConditionEnum.EMPTY.getSymbol());
                if (Objects.isNull(emptySql)) {
                    emptySql = new StringBuffer();
                    emptySql.append("  WHERE  LENGTH (" ).append(teamNameAlias).append(".team_main) = 0");
                }else {
                    emptySql.append("  AND  LENGTH (" ).append(teamNameAlias).append(".team_main) = 0");
                }
                fliterMap.put(ConditionEnum.EMPTY.getSymbol(), emptySql);
            }
        }
    }


    /**
     * @param chartEntity
     * @param isSingle
     * @param stringBuffer
     * @param fields
     * @param sortField
     * @param fliterMap
     * @param pageSize
     * @param from
     * @param isMaxPermission
     * @param groupFields
     * @Param targetFlag  是否是指标图
     */
    public void tableJoin(Pair<GroupSqlVO, HashMap<String, Set<String>>> groupSqlVOHashMapPair, ChartEntity chartEntity, boolean isSingle, StringBuffer stringBuffer, StringBuffer fields,
                          String sortField, Map<String, StringBuffer> fliterMap, Integer pageSize, int from, String groupFields, boolean isMaxPermission, boolean targetFlag) throws XbbException {
        SlaveSourcePojo driverSources = chartEntity.getDriverSources().toJavaObject(SlaveSourcePojo.class);
        XbbTableRefEnum xbbTableRefEnum = XbbTableRefEnum.getByCode(driverSources.getBusinessType());
        String driverTableName = xbbTableRefEnum.getTableName();
        if(StringUtil.isEmpty(driverTableName)){
            throw new XbbException(BiErrorCodeEnum.API_ERROR_241025);
        }
        boolean isPublicFlag = false;
        boolean allPermission = false;
        if (!isMaxPermission) {
            JSONObject permission = chartEntity.getPermissions();
            //数据权限字段
            JSONObject dataPermissionAttr = permission == null ? null : permission.getJSONObject("dataPermissionAttr");
            if (dataPermissionAttr == null || dataPermissionAttr.isEmpty()) {
                allPermission = true;
            }
        }
        if (isSingle) {
            String itemStr = getItemStr(groupSqlVOHashMapPair.getValue(), driverTableName);
            // 增加argmax函数，具体是拼接上data外的字段 : 例如： argMax(department_id, update_time) as department_id
            itemStr = addItemStr(itemStr, fliterMap, driverSources.getFormId().toString(), chartEntity);
            stringBuffer.append("select ").append(fields).append(" from ")
                    .append(" (SELECT ").append(itemStr).append(fliterMap.get(driverSources.getFormId().toString())).append(" )  AS ").append(driverTableName);
            /*if (Objects.equals(driverSources.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
            }*/
            String teamName = getTeamNameByBusinessType(driverSources.getBusinessType());
            //TODO  后面判断超管，且没有团队相关的字段就不join团队表了
            String corpid = chartEntity.getCorpid();
            appendTeam(fliterMap, driverSources.getFormId(), teamName, isPublicFlag, chartEntity, driverTableName, groupFields, isMaxPermission, fields, stringBuffer, corpid, allPermission);
            handlerGroupOrder(groupSqlVOHashMapPair, stringBuffer, sortField, groupFields, driverTableName, targetFlag,fliterMap);
        } else {
            Long formId = driverSources.getFormId();
            String teamName = getTeamNameByBusinessType(driverSources.getBusinessType());
            JSONArray slaveSources = chartEntity.getSlaveSources();
            String itemStr = getLinkAttrs(slaveSources, driverSources, groupSqlVOHashMapPair, driverTableName);
            // 增加argmax函数，具体是拼接上data外的字段 : 例如： argMax(department_id, update_time) as department_id
            itemStr = addItemStr(itemStr, fliterMap, driverSources.getFormId().toString(), chartEntity);
            Integer inData = driverSources.getInData();
            boolean  productRef = false;
            // 关联产品转换
            if (BIProductReformEnum.getProductSubBusList().contains(driverSources.getBusinessType())) {
                BIProductReformEnum biProductReformEnum = BIProductReformEnum.getEnumByProductBusinessType(driverSources.getBusinessType());
                if (Objects.nonNull(biProductReformEnum)) {
                    String linkAttrCopy = biProductReformEnum.getDbFieldLinkMainBusiness();
                    driverSources.setLinkAttrCopy(linkAttrCopy);
                    StringBuilder itemBuilder = new StringBuilder(itemStr);
                    itemBuilder.append(XbbConstant.SQL_COMMA).append(generatargMax(StringUtil.getDataBaseString(linkAttrCopy)));
                    itemBuilder.append(XbbConstant.SQL_COMMA).append(generatargMax(StringUtil.getDataBaseString(RelatedProductConstant.PRODUCT_ID)));
                    itemStr = itemBuilder.toString();
                    inData = 0;
                    productRef = true;
                    // linkAttr为num_98转product_id
                    transform2ProductId(driverSources);
                    // 查询表塞个productId，后面有用
                    if (Objects.equals(chartEntity.getChartType(), ChartTypeEnum.DATA_QUERY_TABLE.getCode())) {
                        fields.append(XbbConstant.SQL_COMMA).append(driverTableName).append(XbbConstant.POINT).append(StringUtil.getDataBaseString(RelatedProductConstant.PRODUCT_ID)).append(" AS productId");
                    }
                }
            }
            stringBuffer.append("select ").append(fields).append(" from ")
                    .append(" (SELECT  ").append(itemStr).append(fliterMap.get(formId.toString())).append(" )  AS ").append(driverTableName);
            String corpid = chartEntity.getCorpid();
            /*if (Objects.equals(driverSources.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
            }*/
            //主表的团队
            //TODO  后面判断超管，且没有团队相关的字段就不join团队表了
            appendTeam(fliterMap, formId, teamName, isPublicFlag, chartEntity, driverTableName, groupFields, isMaxPermission, fields, stringBuffer, corpid, allPermission);
            if (CollectionsUtil.isNotEmpty(slaveSources)) {
                Map<String, Integer> map = new HashMap(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put(driverTableName, 0);
                for (int i = 0; i < slaveSources.size(); i++) {
                    JSONObject slaveJson = slaveSources.getJSONObject(i);
                    String sTableName;
                    Integer businessType = slaveJson.getInteger("businessType");
                    if (Objects.equals(slaveJson.getInteger("saasMark"), SaasMarkEnum.SAAS.getCode())) {
                        XbbTableRefEnum tableRefEnum = XbbTableRefEnum.getByCode(businessType);
                        sTableName = tableRefEnum.getTableName();
                    } else {
                        sTableName = XbbTableRefEnum.PAAS.getTableName();
                    }
                    if(StringUtil.isEmpty(sTableName)){
                        LOG.error("hello",driverTableName+"===="+"businessType" +driverSources.getBusinessType()+"======"+XbbTableRefEnum.getByCode(driverSources.getBusinessType()).toString());
                        throw new XbbException(BiErrorCodeEnum.API_ERROR_241025);
                    }
                    String itemStrS = null;
                    Integer inDataFollow = slaveJson.getInteger("inData");
                    //i =0 的时候已初始化声明
                    if (i == 1) {
                        inData = driverSources.getSecondInData();
                    } else if (i == 2) {
                        inData = driverSources.getLinkAttrCInData();
                    } else if (i == 3) {
                        inData = driverSources.getLinkAttrDInData();
                    } else if (i == 4) {
                        inData = driverSources.getLinkAttrEInData();
                    }
                    String linkAttrCopyFollow = slaveJson.getString("linkAttrCopy");
                    String sTableNameAlais = sTableName;
                    if (map.containsKey(sTableName)) {
                        int value = map.get(sTableName) + 1;
                        sTableNameAlais = sTableName + value;
                        map.put(sTableName, value);
                    } else {
                        map.put(sTableName, 0);
                    }
                    if (Objects.equals(0, inDataFollow) && !StringUtils.equals("dataId", linkAttrCopyFollow) &&
                            !Objects.equals("id", linkAttrCopyFollow) &&
                            !StringUtils.equals(XbbTableRefEnum.CONTRACT_PERFORMANCE.getTableName(), sTableName)) {
                        if (Objects.equals(sTableName, XbbTableRefEnum.REFUND.getTableName())) {
                            linkAttrCopyFollow = RefundEnum.RED_CONTRACT_ID.getAttr();
                        }
                        linkAttrCopyFollow = StringUtil.getDataBaseString(linkAttrCopyFollow);
                        itemStrS = addLinkAttrFollow(sTableNameAlais, groupSqlVOHashMapPair.getValue(), linkAttrCopyFollow);
                    } else {
                        itemStrS = getItemStr(groupSqlVOHashMapPair.getValue(), sTableNameAlais);
                    }
                    itemStrS = addItemStr(itemStrS, fliterMap, slaveJson.getLong(FieldAttrConstant.FORMID).toString(), chartEntity);
                    stringBuffer.append(XbbConstant.LEFT_SEMI_JOIN).append("( ").append("select ").append(itemStrS)
                            .append(fliterMap.get(slaveJson.getLong("formId").toString())).append(" )  AS ").append(sTableNameAlais)
                            .append(" ON ");
                    String linkAttrCopy = ReflectHelper.valueGet(driverSources, getLinkAttrName(i)).toString();
                    if (Objects.equals(XbbRefTypeEnum.CONTRACT_PERFORMANCE.getCode(), driverSources.getBusinessType())) {
                        inData = 0;
                        linkAttrCopy = ContractPerformanceEnum.getRealAttr(linkAttrCopy);
                    }
                    if(productRef){
                        String linkAttr = driverSources.getLinkAttr();
                        if (i == 1) {
                            linkAttr = driverSources.getLinkAttrB();
                        } else if (i == 2) {
                            linkAttr = driverSources.getLinkAttrC();
                        } else if (i == 3) {
                            linkAttr = driverSources.getLinkAttrD();
                        } else if (i == 4) {
                            linkAttr = driverSources.getLinkAttrE();
                        }
                        if (Objects.equals(linkAttr,RelatedProductConstant.LINK_MAINBUSINESS_ATTR) || Objects.equals(linkAttr,RelatedProductConstant.LINK_PRODUCT_ATTR)){
                            inData = 0;
                        }
                    }
                    appendJoinSql(chartEntity.getSingle(), slaveJson, stringBuffer, linkAttrCopy, driverTableName, sTableNameAlais, inData, inDataFollow, corpid, fliterMap, isMaxPermission,allPermission);
                }
            }
            handlerGroupOrder(groupSqlVOHashMapPair, stringBuffer, sortField, groupFields, driverTableName,fliterMap);
        }
        //分页
        stringBuffer.append(" limit ").append(from).append(",").append(pageSize);

        StringBuffer subSqlBuilder = new StringBuffer();
        List<String> subQuerySqlOfCountList = groupSqlVOHashMapPair.getKey().getSubQuerySqlOfCountList();
        if(CollectionsUtil.isNotEmpty(subQuerySqlOfCountList)){
            //子查询内层完整SQL语句;
            groupSqlVOHashMapPair.getKey().setSubCompleteSqlOfCount(stringBuffer.toString());

            //子查询外层处理(计算公式中存在COUNT)
            String subSqlItem = groupSqlVOHashMapPair.getKey().getSubSqlOfCount();
            String subOrderSqlOfCount = groupSqlVOHashMapPair.getKey().getSubOrderSqlOfCount();

            subSqlBuilder.append(XbbConstant.SELECT).append(subSqlItem).append(XbbConstant.SPACE)
                    .append(XbbConstant.FROM).append(XbbConstant.L_P).append(stringBuffer).append(XbbConstant.R_P).append(XbbConstant.SPACE);
            if(StringUtils.isNotBlank(subOrderSqlOfCount)){
                subSqlBuilder.append(XbbConstant.ORDER_BY).append(subOrderSqlOfCount);
            }

            //新增外层SQL，并重置
            stringBuffer.delete(BasicConstant.ZERO,stringBuffer.length());
            stringBuffer.append(subSqlBuilder);
        }
    }

    /**
     * 新增itemStr参数的函数
     *
     * @param itemStr       就是最终sql里面select后面的参数（argMax函数）函数
     * @param filterMap     过滤的条件
     * @param formId        表单Id
     * @param chartEntity   图表实体
     * @return 修改后的itemStr
     */
    private String addItemStr(String itemStr, Map<String, StringBuffer> filterMap, String formId, ChartEntity chartEntity) {
        StringBuffer filterStringBuffer = filterMap.get(formId);
        if (Objects.isNull(filterStringBuffer)) {
            return itemStr;
        }
        String selectItems = filterStringBuffer.toString();
        String[] conditionArray = selectItems.split("having");
        if (conditionArray.length == BasicConstant.TWO) {
            String[] conditions = conditionArray[BasicConstant.ONE].split("AND");
            for (String condition : conditions) {
                String trimCondition = condition.trim();
                String[] attr = trimCondition.split(" ");
                if (!itemStr.contains(attr[BasicConstant.ZERO])) {
                    boolean isDataIn = isDataIn(chartEntity, attr[BasicConstant.ZERO]);
                    // 不是data内的字段才需要拼接argMax函数
                    if (!isDataIn) {
                        itemStr = itemStr + "," + generatargMax(attr[BasicConstant.ZERO]);
                    }
                }
            }
        }
        return itemStr;
    }

    /**
     * 当前条件是否在data字段内
     *
     * @param chartEntity 图表试图
     * @param attr        条件属性
     * @return true ： 在data字段内。 false ： 不在data字段内
     */
    private boolean isDataIn(ChartEntity chartEntity, String attr) {
        String humpAttr = EsUtil.getHumpString(attr);
        JSONArray filter = chartEntity.getFilter();
        JSONArray search = chartEntity.getSearch();

        filter.addAll(search);
        if (CollectionsUtil.isEmpty(filter)) {
            return true;
        }
        for (int i = 0; i < filter.size(); i++) {
            JSONObject filterObject = filter.getJSONObject(i);
            String filterAttr = filterObject.getString(FieldAttrConstant.ATTR);
            if (Objects.equals(filterAttr, humpAttr)) {
                Integer fieldType = filterObject.getInteger(FieldAttrConstant.FIELD_TYPE);
                return EsUtil.setInData(fieldType);
            }
        }
        return true;
    }

    private void appendTeam(Map<String, StringBuffer> fliterMap, Long formId, String teamName, boolean isPublicFlag, ChartEntity chartEntity, String driverTableName, String groupFields, boolean isMaxPermission, StringBuffer fields, StringBuffer stringBuffer, String corpid, boolean allPermission) throws XbbException {
        StringBuffer condition = fliterMap.get(formId + "_" + teamName);
        isPublicFlag = isPublicFlag(chartEntity, driverTableName, isPublicFlag);
        if (isPublicFlag && groupFields != null && groupFields.contains(XbbTableRefEnum.CUSTOMER_TEAM.getTableName())) {
            throw new XbbException(BiErrorCodeEnum.API_ERROR_241020);
        }
        Boolean[] booleans = {isMaxPermission, isPublicFlag,allPermission};
        if (isNeedTeam(booleans, fields, condition, teamName)) {
            appendTeamJoinSql(stringBuffer, driverTableName, formId, teamName, corpid, fliterMap, isMaxPermission);
        }
    }

    /**
     * @return java.lang.String
     * @author gzt
     * @Description 循环添加关联字段到selectItem中
     * @Date 9:58 2022/2/16
     **/

    public String getLinkAttrs(JSONArray slaveSources, SlaveSourcePojo driverSources, Pair<GroupSqlVO, HashMap<String, Set<String>>> groupSqlVOHashMapPair, String driverTablename) {
        if (Objects.isNull(slaveSources) || Objects.isNull(driverSources) || Objects.isNull(groupSqlVOHashMapPair) || StringUtils.isEmpty(driverTablename)) {
            return null;
        }
        Integer inData = driverSources.getInData();
        HashMap<String, Set<String>> mapPairValue = groupSqlVOHashMapPair.getValue();
        for (int i = 0; i < slaveSources.size(); i++) {
            if (i == 0) {
            } else if (i == 1) {
                inData = driverSources.getSecondInData();
            } else if (i == 2) {
                inData = driverSources.getLinkAttrCInData();
            } else if (i == 3) {
                inData = driverSources.getLinkAttrDInData();
            } else if (i == 4) {
                inData = driverSources.getLinkAttrEInData();
            }
            String linkAttrCopy = ReflectHelper.valueGet(driverSources, getLinkAttrName(i)).toString();
            if (Objects.equals(0, inData) && !StringUtils.equals("dataId", linkAttrCopy) &&
                    !StringUtils.equals(XbbTableRefEnum.CONTRACT_PERFORMANCE.getTableName(), driverTablename) &&
                    (Objects.equals(XbbTableRefEnum.WORK_ORDER_V2_NODE_LOG_INFO.getTableName(), driverTablename) && Objects.equals(StringConstant.WORK_ORDER_ID, linkAttrCopy))) {
                linkAttrCopy = StringUtil.getDataBaseString(linkAttrCopy);
                mapPairValue = addLinkAttr(driverTablename, mapPairValue, linkAttrCopy);
            }
        }
        String itemStr = getItemStr(mapPairValue, driverTablename);
        return itemStr;
    }

    private HashMap<String, Set<String>> addLinkAttr(String tablename, HashMap<String, Set<String>> mapPairValue, String linkAttrCopyFollow) {
        if (handlerLinkAttrs(tablename, mapPairValue, linkAttrCopyFollow)) {
            return null;
        }
        return mapPairValue;
    }

    private String addLinkAttrFollow(String tablename, HashMap<String, Set<String>> mapPairValue, String linkAttrCopyFollow) {
        if (handlerLinkAttrs(tablename, mapPairValue, linkAttrCopyFollow)) {
            return null;
        }
        return getItemStr(mapPairValue, tablename);
    }

    private boolean handlerLinkAttrs(String tablename, HashMap<String, Set<String>> mapPairValue, String linkAttrCopyFollow) {
        if (StringUtils.isEmpty(tablename) || Objects.isNull(mapPairValue) || StringUtils.isEmpty(linkAttrCopyFollow)) {
            return true;
        }
        Set<String> vSets = mapPairValue.get(tablename);
        if (Objects.isNull(vSets)) {
            vSets = Sets.newHashSet();
        }
        vSets.add(generatargMax(linkAttrCopyFollow));
        mapPairValue.put(tablename, vSets);
        return false;
    }

    /**
     * @param chartEntity
     * @param driverTableName
     * @param isPublicFlag
     * @return boolean
     * @throws
     * @Description 根据ChartEntity、driverTableName获取是否公海
     * @Date 14:53 2022/1/6
     **/

    private boolean isPublicFlag(ChartEntity chartEntity, String driverTableName, boolean isPublicFlag) {
        if (chartEntity != null ) {
            if(StringUtils.equals(driverTableName, XbbTableRefEnum.CUSTOMER_MANAGEMENT.getTableName()) || StringUtils.equals(driverTableName, XbbTableRefEnum.CLUE.getTableName())){
                JSONArray conditionJson = chartEntity.getFilter();
                if (conditionJson != null) {
                    conditionJson = JSON.parseArray(conditionJson.toJSONString());
                    isPublicFlag = ChartUtil.isPublicFlag(conditionJson);
                }
                if(!isPublicFlag){
                    JSONArray searchJson = chartEntity.getSearch();
                    searchJson = JSON.parseArray(searchJson.toJSONString());
                    isPublicFlag = ChartUtil.isPublicFlag(searchJson);
                }
            }
        }
        return isPublicFlag;
    }

    public void tableJoin(Pair<GroupSqlVO, HashMap<String, Set<String>>> groupSqlVOHashMapPair, ChartEntity chartEntity, boolean isSingle, StringBuffer stringBuffer, StringBuffer fields,
                          String sortField, Map<String, StringBuffer> fliterMap, Integer pageSize, int from, String groupFields, boolean isMaxPermission) throws XbbException {
        tableJoin(groupSqlVOHashMapPair, chartEntity, isSingle, stringBuffer, fields,
                sortField, fliterMap, pageSize, from, groupFields, isMaxPermission, false);
    }

    /**
     * @return void
     * @throws
     * @Description 处理默认排序
     * @Date 19:52 2021/12/29
     * @Param [groupSqlVOHashMapPair, stringBuffer, sortField, groupFields, driverTableName]
     * @Param targetFlag  是否是指标图
     **/

    private void handlerGroupOrder(Pair<GroupSqlVO, HashMap<String, Set<String>>> groupSqlVOHashMapPair, StringBuffer stringBuffer, String sortField, String groupFields, String driverTableName, boolean targetFlag,Map<String, StringBuffer> fliterMap) {
        if (StringUtil.isNotEmpty(groupFields)) {
            stringBuffer.append(XbbConstant.GROUP_BY).append(groupFields);
        }
        StringBuffer emptySql = fliterMap.get(ConditionEnum.EMPTY.getSymbol());
        if (!Objects.isNull(emptySql)) {
            stringBuffer.append(emptySql);
        }
        if (StringUtil.isNotEmpty(sortField)) {
            stringBuffer.append(XbbConstant.ORDER_BY).append(sortField);
        } else {
            if (StringUtil.isNotEmpty(groupFields)) {
                fieldSort(stringBuffer,groupSqlVOHashMapPair);
            } else {
                if (!targetFlag) {
                    stringBuffer.append(XbbConstant.ORDER_BY).append(String.format("%s%s%s%s%s", driverTableName, XbbConstant.POINT, ParameterConstant.ID, XbbConstant.SPACE, XbbConstant.ORDER_DESC));
                }
            }
        }
    }

    private void fieldSort(StringBuffer stringBuffer, Pair<GroupSqlVO, HashMap<String, Set<String>>> groupSqlVOHashMapPair) {
        GroupSqlVO groupSqlVO = groupSqlVOHashMapPair.getKey();
        //分组字段
        List<String> groupFieldsList = groupSqlVO.getGroupFieldsList();
        //字段类型为下拉单选类型的分组字段
        Map<String, FieldAttrPojo> comboFieldMap = groupSqlVO.getComboFieldMap();
        List<String> tmpSqlList = new ArrayList<>();
        //没有下拉单选的字段
        if(comboFieldMap == null || comboFieldMap.size() == 0){
            //使用原始sql
            tmpSqlList = groupFieldsList;
        }else{
            //置换下拉字段的sql
            for (String groupSql : groupFieldsList) {
                if (comboFieldMap.containsKey(groupSql)) {
                    FieldAttrPojo fieldAttrPojo = comboFieldMap.get(groupSql);
                    String multiIf = multiIf(groupSql.split("AS")[0], fieldAttrPojo.getItems(), "");
                    if (StringUtils.isNotBlank(multiIf)) {
                        tmpSqlList.add(multiIf);
                    }
                } else {
                    tmpSqlList.add(groupSql);
                }
            }
        }
        statisticsTableVOHelper.defaultFieldSort(stringBuffer,tmpSqlList);
    }

    /**
     * 多条件语句sql
     *
     * @param key 主条件的key
     * @param items key对应的值
     * @param elseStr else 的值
     * @return java.lang.String
     * @author zyy
     * @date 2022/8/15
     * @version v1.0
     */
    private String multiIf(String key, List<ItemPoJo> items, String elseStr) {
        if(CollectionsUtil.isEmpty(items)){
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(XbbConstant.MULTI_IF).append(XbbConstant.L_P);
        //主条件
        for (int i = 0; i < items.size(); i++) {
            sb.append(key).append(XbbConstant.EQUAL)
                    .append(XbbConstant.SINGLE_QUOTES).append(items.get(i).getValue()).append(XbbConstant.SINGLE_QUOTES)
                    .append(XbbConstant.SQL_COMMA).append(XbbConstant.SINGLE_QUOTES).append(items.size() - i).append(XbbConstant.SINGLE_QUOTES)
                    .append(XbbConstant.SQL_COMMA);
        }
        //else条件
        String elseSql = StringUtils.isNotBlank(elseStr) ? elseStr : "NULL";
        sb.append(elseSql);
        sb.append(XbbConstant.R_P);
        return sb.toString();
    }

    /**
     * if函数
     *
     * @param cond  判断语句
     * @param condValue  判断值
     * @param elseStr  否则语句
     * @return java.lang.String
     * @author zyy
     * @date 2022/8/24
     * @version v1.0
     */
    public static String ifFunction(String cond,String symbol,String condValue, String defaultValue ,String elseStr){
        StringBuilder sb = new StringBuilder(XbbConstant.L_P);
        sb.append(XbbConstant.IF).append(XbbConstant.L_P)
                .append(cond).append(symbol).append(condValue).append(XbbConstant.SQL_COMMA).append(defaultValue)
                .append(XbbConstant.SQL_COMMA).append(elseStr);
        sb.append(XbbConstant.R_P).append(XbbConstant.R_P);
        return sb.toString();
    }

    private void handlerGroupOrder(Pair<GroupSqlVO, HashMap<String, Set<String>>> groupSqlVOHashMapPair, StringBuffer stringBuffer, String sortField, String groupFields, String driverTableName,Map<String, StringBuffer> fliterMap) {
        handlerGroupOrder(groupSqlVOHashMapPair, stringBuffer, sortField, groupFields, driverTableName, false, fliterMap);
    }

    /**
     * @return java.lang.String
     * @throws
     * @Description
     * @Date 10:45 2021/12/22
     * @Param [itemMap, fields, itemStr, sTableName]
     **/

    private String getItemStr(HashMap<String, Set<String>> itemMap, String sTableName) {
        String itemStr = "id";
        if (null != itemMap && StringUtils.isNotEmpty(sTableName) && itemMap.get(sTableName) != null) {
            itemStr = MessageFormat.format("{0}{1}{2}", itemStr, XbbConstant.SQL_COMMA, itemMap.get(sTableName).stream().collect(Collectors.joining(XbbConstant.SQL_COMMA)));
        }
        String itemDate = "";
        itemDate = handleDataAndDel(sTableName, itemDate);
        itemDate = handleFlowStatusByTablename(sTableName, itemDate);
        itemDate = appendArgMaxPara(sTableName, itemStr, itemDate);
        itemStr = MessageFormat.format("{0}{1}{2}", itemStr, XbbConstant.SQL_COMMA, itemDate);
        return itemStr;
    }

    private String handleDataAndDel(String sTableName, String itemDate){
        List<String> list = Arrays.asList(XbbTableRefEnum.WORK_ORDER_V2_NODE_LOG_INFO.getTableName());
        if (!list.contains(sTableName)){
            itemDate += "argMax(data,update_time) as data,argMax(del,update_time) as del";
        }else {
            itemDate += "argMax(del,update_time) as del";
        }
        return itemDate;
    }

    private String handleFlowStatusByTablename(String sTableName, String itemDate) {
        if (!Objects.equals(sTableName, XbbTableRefEnum.CONTRACT_PERFORMANCE.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.CONTRACT_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.SALES_OPPORTUNITY_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.QUOTATION_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.SUPPLIER_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.PURCHASE_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.RETURNEDPURCHASE_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.BOM_BILL_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.PRODUCTION_ORDER_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.ASSEMBLE_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.INVENTORY_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.TRANSFER_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.INSTOCK_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.OUTSTOCK_PRODUCT.getTableName())
                && !Objects.equals(sTableName, XbbTableRefEnum.WORK_ORDER_V2_NODE_LOG_INFO.getTableName())
        ){
                itemDate = itemDate + ",argMax(flow_status,update_time) as flow_status ";
        }
        return itemDate;
    }

    private String appendArgMaxPara(String sTableName, String itemStr, String itemDate) {
        if (StringUtils.equals(sTableName, XbbTableRefEnum.CONTRACT_PERFORMANCE.getTableName())) {
            itemDate = Arrays.stream(ContractPerformanceEnum.values()).filter(a -> !a.getSaasAttr().contains("Time"))
                    .map(a -> StringUtil.getDataBaseString(a.getSaasAttr()))
                    .map(b -> "argMax(" + b + ",update_time) as "
                            + b).collect(Collectors.joining(","));
            //itemDate = "argMax(is_sign,update_time) as is_sign,argMax(user_id,update_time) as user_id,argMax(contract_id,update_time) as contract_id,argMax(del,update_time) as del  ";
            itemDate = itemDate + ",argMax(del,update_time) as del ";
        }else if (Objects.equals(sTableName, XbbTableRefEnum.PURCHASE_PRODUCT.getTableName())) {
            String instockNum = StringUtil.getDataBaseString(RelatedProductConstant.INSTOCK_NUM);
            if (Objects.nonNull(itemStr) && !StringUtils.contains(itemStr,instockNum)) {
                itemDate = itemDate + ",argMax(" + instockNum + ",update_time) as " + instockNum + " ";
            }
            String outstockNum = StringUtil.getDataBaseString(RelatedProductConstant.OUTSTOCK_NUM);
            if (Objects.nonNull(itemStr) && !StringUtils.contains(itemStr,outstockNum)) {
                itemDate = itemDate + " ,argMax(" + outstockNum + ",update_time) as " + outstockNum + " ";
            }
        }else if (Objects.equals(sTableName, XbbTableRefEnum.TRANSFER_PRODUCT.getTableName())) {
            String instockNum = StringUtil.getDataBaseString(RelatedProductConstant.INSTOCK_NUM);
            if (Objects.nonNull(itemStr) && !StringUtils.contains(itemStr,instockNum)) {
                itemDate = itemDate + ",argMax(" + instockNum + ",update_time) as " + instockNum + " ";
            }
        }else if (Objects.equals(sTableName, XbbTableRefEnum.PRODUCTION_ORDER_PRODUCT.getTableName())
                || Objects.equals(sTableName, XbbTableRefEnum.RETURNEDPURCHASE_PRODUCT.getTableName())) {
            String outstockNum = StringUtil.getDataBaseString(RelatedProductConstant.OUTSTOCK_NUM);
            if (Objects.nonNull(itemStr) && !StringUtils.contains(itemStr,outstockNum)) {
                itemDate = itemDate + " ,argMax(" + outstockNum + ",update_time) as " + outstockNum + " ";
            }
        }
        return itemDate;
    }


    /**
     * 文本加引号
     *
     * @param fieldType
     * @param value
     * @return java.lang.Object
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2021/11/30 17:28
     * @version 1.0
     */
    private static Object handleText(Integer fieldType, Object value) {
        if (FieldTypeEnum.isTextType(fieldType)) {
            value = "'" + value + "'";
        }
        return value;
    }

    /**
     * attr加单引号
     *
     * @param attr
     * @return java.lang.String
     * @author xinpeng.jiang
     * @date 2021/12/23 10:20
     * @version 1.0
     */
    private String formatSingleQuotes4Attr(String attr) {
        return "'" + attr + "'";
    }

    /**
     * 团队筛选解析
     *
     * @param fliterMap     查询语句载体
     * @param conditionEnum 筛选类型
     * @param condition     筛选详情
     * @param isTeam        判断该表单是否走团队逻辑
     * @param isMain        判断是负责人或协同人
     * @param isPublicFlag  是否是公海客户 del = -1
     * @param businessType  业务code
     * @author zhouwq
     * @date 2019/5/7 15:59
     */
    private static void teamConditionSymbolChoose(Map<String, StringBuffer> fliterMap, ConditionEnum conditionEnum, ConditionsEntityExt condition, boolean isTeam,
                                                  Integer isMain, boolean isPublicFlag, boolean isSingle, Integer businessType) {
/*        String attr = condition.getAttr();
        Integer fieldType = condition.getFieldType();
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
        if (!isSingle) {
            attr = condition.getOriginalAttr();
        }
        attr = StringUtil.getDataBaseString(attr);*/
        //转到对应的团队下
        String teamName = getTeamNameByBusinessType(condition.getBusinessType());
        Long formId = condition.getFormId();
        StringBuffer stringBuffer = fliterMap.get(formId + "_" + teamName);
        if (Objects.isNull(stringBuffer)) {
            stringBuffer = new StringBuffer();
            fliterMap.put(formId + "_" + teamName, stringBuffer);
        }
        List<Object> values = condition.getValue();
        List<String> userIdList = new ArrayList<>();
        for (int i = 0; i < values.size(); i++) {
            String obj = values.get(i).toString();
            //穿透是字符串有逗号拼装，筛选是数组
            if (obj.contains(",")) {
                String[] array = obj.split(",");
                userIdList.addAll(Arrays.asList(array));
            } else {
                userIdList.add(obj);
            }
        }
        switch (conditionEnum) {
            case EQUAL:
            case ALLINCLUDE:
                if (isTeam) {
                    StringBuilder valuesString = new StringBuilder();
                    valuesString.append("[");
                    for (int i = 0; i < userIdList.size(); i++) {
                        if (i > 0) {
                            valuesString.append(",");
                        }
                        valuesString.append("'").append(userIdList.get(i)).append("'");
                    }
                    valuesString.append("]");
                    String team = XbbConstant.TEAM_MAIN;
                    if (isMain == 0) {
                        team = XbbConstant.TEAM_CO;
                    }
                    stringBuffer.append(XbbConstant.AND).append("hasAll(" + team + "," + valuesString + ")").append(XbbConstant.SPACE);
                    stringBuffer.append(XbbConstant.AND).append(XbbConstant.LENGTH + "(" + valuesString + ")").append(" = ").append(XbbConstant.LENGTH).append("(" + team + " )");
                }
                break;
            case IN:
            case INCLUDE:
                if (isTeam) {
                    StringBuilder valuesString = new StringBuilder();
                    valuesString.append("(");
                    for (int i = 0; i < userIdList.size(); i++) {
                        if (i > 0) {
                            valuesString.append(" or ");
                        }
                        String team = XbbConstant.TEAM_MAIN;
                        if (isMain == 0) {
                            team = XbbConstant.TEAM_CO;
                        }
                        valuesString.append("has(" + team + ",'" + userIdList.get(i) + "')");
                    }
                    valuesString.append(")");
                    stringBuffer.append(XbbConstant.AND).append(valuesString).append(XbbConstant.SPACE);
                }
                break;
            case NOEQUAL:
            case NOIN:
                break;
            case EMPTY:
                fliterMap.put(formId + "_" + teamName+"_"+ConditionEnum.EMPTY.getSymbol(), new StringBuffer("true"));
                break;
            case NOEMPTY:
                break;
            default:
                break;
        }
    }

    /**
     * 查询时默认的一些规则条件组装
     *
     * @param corpid
     * @param formId
     * @param businessType
     * @param filterMap    查询条件
     * @param formIdAttr   多表对应的attr
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2021/12/22 10:18
     * @version 1.0
     */
    private void addDefaultFilter(String corpid, Long formId, Integer businessType, Map<String, StringBuffer> filterMap, JSONObject formIdAttr) throws XbbException {
        StringBuffer stringBuffer = new StringBuffer();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        String data = XbbConstant.DATA + SymbolConstant.COMMA_ENGLISH;
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                //红冲合同不展示
                String attr = formatSingleQuotes4Attr(ContractEnum.IS_RED.getAttr());
                stringBuffer.append(XbbConstant.SPACE)
                        .append(XbbConstant.AND).append(XbbConstant.SPACE)
                        .append(XbbConstant.JSON_EXTRACT_INT).append(XbbConstant.L_P).append(data).append(attr).append(XbbConstant.R_P).append(XbbConstant.SPACE)
                        .append(ConditionEnum.EQUAL.getReplaceSymbol()).append(XbbConstant.SPACE)
                        .append(BasicConstant.ZERO);
                break;
            case PRODUCT:
                //多表时不考虑
                if (formIdAttr == null || formIdAttr.size() == 0) {
                    //只查子产品
                    String s = formatSingleQuotes4Attr(ProductEnum.PARENT_ID.getAttr());
                    stringBuffer.append(XbbConstant.SPACE)
                            .append(XbbConstant.AND).append(XbbConstant.SPACE)
                            .append(XbbConstant.JSON_EXTRACT_INT).append(XbbConstant.L_P).append(data).append(s).append(XbbConstant.R_P).append(XbbConstant.SPACE)
                            .append(ConditionEnum.NOEQUAL.getReplaceSymbol()).append(XbbConstant.SPACE)
                            .append(BasicConstant.ZERO);
                }
                break;
            case WORK_ORDER:
                //多表展示不考虑
                if (formIdAttr == null || formIdAttr.size() == 0) {
                    stringBuffer.append(XbbConstant.SPACE)
                            .append(XbbConstant.AND).append(XbbConstant.SPACE)
                            .append(FieldTypeEnum.WORK_ORDER_ROB.getAlias()).append(XbbConstant.SPACE)
                            .append(ConditionEnum.EQUAL.getReplaceSymbol()).append(XbbConstant.SPACE)
                            .append(WorkOrderTypeEnum.NORMAL.getCode());
                }
                break;
            case CUSTOMER_COMMUNICATE:
                //跟进记录多表已经在数据端处理
                //过滤项目日志
                String autoGen = formatSingleQuotes4Attr(CustomerCommunicateEnum.AUTO_GEN.getAttr());
                stringBuffer.append(XbbConstant.SPACE)
                        .append(XbbConstant.AND).append(XbbConstant.SPACE)
                        .append(XbbConstant.JSON_EXTRACT_INT).append(XbbConstant.L_P).append(data).append(autoGen).append(XbbConstant.R_P).append(XbbConstant.SPACE)
                        .append(ConditionEnum.EQUAL.getReplaceSymbol()).append(XbbConstant.SPACE)
                        .append(BasicConstant.ZERO);
                break;
            case PAYMENT_SHEET:
            case WRITE_OFF_PREPAYMENT:
            case RED_PAYMENT_SHEET:
            case RED_PREPAYMENT:
            case RED_WRITE_OFF_PREPAYMENT:
            case RED_WRITE_OFF_BALANCE:
            case PREPAYMENT:
            case BAD_DEBT:
            case PAY_SHEET:
            case WRITE_OFF_PREPAY:
            case RED_WRITE_OFF_PAY:
            case RED_PREPAY:
            case RED_WRITE_OFF_PREPAY:
            case PREPAY:
            case BAD_PAY:
                List<Integer> sheetTypeList;
                if (formIdAttr != null && formIdAttr.size() > 0) {
                    sheetTypeList = SheetAloneEnum.getNotParentCodeList();
                } else {
                    sheetTypeList = SheetAloneEnum.getNotChildCodeList();
                }
                stringBuffer.append(XbbConstant.SPACE)
                        .append(XbbConstant.AND).append(XbbConstant.SPACE)
                        .append(FieldTypeEnum.SHEET_ALONE.getAlias()).append(XbbConstant.SPACE);
                stringBuffer.append(ConditionEnum.IN.getReplaceSymbol()).append(XbbConstant.SPACE)
                        .append(sheetTypeList);

                break;
            default:
                break;
        }
        // 塞回去，没有初始化一个
        filterMap.computeIfAbsent(String.valueOf(formId), v -> initSqlString(corpid, formId, businessType, filterMap, null, null)).append(stringBuffer);
    }

    /**
     * 产品分类筛选
     *
     * @param corpid
     * @param chartEntity
     * @param filterMap   筛选条件map
     * @param formIdAttr  多表attr映射
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2021/12/27 19:52
     * @version 1.0
     */
    private void parseProductCategory(String corpid, ChartEntity chartEntity, Map<String, StringBuffer> filterMap, JSONObject formIdAttr) {
        List<Double> doubleList = new ArrayList<>();
        JSONArray allJsonArr = new JSONArray();
        JSONArray chartClassify = chartEntity.getChartClassify();
        if(CollectionsUtil.isNotEmpty(chartClassify)){
            allJsonArr.fluentAddAll(chartClassify);
        }
        if(CollectionsUtil.isNotEmpty(chartEntity.getChartSeries())){
            allJsonArr.fluentAddAll(chartEntity.getChartSeries());
        }
        if(CollectionsUtil.isNotEmpty(chartEntity.getRowGroupAttr())){
            allJsonArr.fluentAddAll(chartEntity.getRowGroupAttr());
        }
        if(CollectionsUtil.isNotEmpty(chartEntity.getColGroupAttr())){
            allJsonArr.fluentAddAll(chartEntity.getColGroupAttr());
        }
        List<FieldAttrPojo> fieldAttrPojoList = JSON.parseArray(JSON.toJSONString(allJsonArr, SerializerFeature.DisableCircularReferenceDetect), FieldAttrPojo.class);
        for (FieldAttrPojo fieldAttrPojo : fieldAttrPojoList) {
            Integer businessType = fieldAttrPojo.getBusinessType();
            Long formId = fieldAttrPojo.getFormId();
            if (Objects.equals(XbbRefTypeEnum.PRODUCT.getCode(), businessType) && ProductEnum.CATEGORY_ID.getAttr().equals(fieldAttrPojo.getOriginalAttr())) {
                JSONArray selectedCategory = fieldAttrPojo.getSelectedCategory();
                if (CollectionsUtil.isEmpty(selectedCategory)) {
                    return;
                }
                for (int j = 0; j < selectedCategory.size(); j++) {
                    JSONObject categoryObj = selectedCategory.getJSONObject(j);
                    doubleList.add(categoryObj.getDoubleValue(ParameterConstant.ID));
                }
                String attr = formatSingleQuotes4Attr(ProductEnum.CATEGORY_ID.getAttr());
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(XbbConstant.SPACE)
                        .append(XbbConstant.AND).append(XbbConstant.SPACE)
                        .append(XbbConstant.JSON_EXTRACT_DOUBLE).append(XbbConstant.L_P).append(XbbConstant.DATA).append(SymbolConstant.COMMA_ENGLISH).append(attr).append(XbbConstant.R_P).append(XbbConstant.SPACE)
                        .append(ConditionEnum.IN.getReplaceSymbol()).append(XbbConstant.SPACE)
                        .append(doubleList);
                // 塞回去，没有初始化一个
                filterMap.computeIfAbsent(String.valueOf(formId), v -> initSqlString(corpid, formId, businessType, filterMap, null, null)).append(stringBuilder);
            }
        }
    }

    /**
     * @return void
     * @throws
     * @Description
     * @Date 9:49 2021/12/30
     * @Param [corpid, fliterMap, conditionEnum, condition, isSingle]
     **/

    private void subFormConditionSymbolChoose(String corpid, Map<String, StringBuffer> fliterMap, ConditionEnum conditionEnum,
                                              ConditionsEntityExt condition, boolean isSingle, Integer businessType) {
        commonConditionSymbolChoose(corpid, fliterMap, conditionEnum, condition, isSingle, businessType);
    }

    /**
     * 如果主表是关联产品，linkAttr为num_98的时候，转为product_id
     *
     * @param driverSources 主表
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2022/1/12 20:45
     * @version 1.0
     */
    private void transform2ProductId(SlaveSourcePojo driverSources) {
        // i为从表数量-1，因为第一张从表必定关联产品对应的业务表，不需要在这转换
        for (int i = 0; i < 4; i++) {
            String linkAttrName = getLinkAttrName(i + 1);
            if (RelatedProductConstant.LINK_PRODUCT_ATTR.equals(ReflectHelper.valueGet(driverSources, linkAttrName))) {
                ReflectHelper.valueSet(driverSources, linkAttrName, StringUtil.getDataBaseString(RelatedProductConstant.PRODUCT_ID));
            }
        }
    }

    /**
     * 根据顺序获取对应linkAttrCopy
     *
     * @param num
     * @return java.lang.String
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2022/1/12 21:07
     * @version 1.0
     */
    private String getLinkAttrName(int num) {
        switch (num) {
            case 0:
                return "linkAttrCopy";
            case 1:
                return "linkAttrBCopy";
            case 2:
                return "linkAttrCCopy";
            case 3:
                return "linkAttrDCopy";
            case 4:
                return "linkAttrECopy";
            default:
                break;
        }
        return "linkAttrCopy";
    }

    /**
     * 文本加引号
     *
     * @param text
     * @return java.lang.String
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2022/1/14 16:47
     * @version 1.0
     */
    public static String format4Text(String text) {
        return "'" + text + "'";
    }

    /**
     * 子查询SQL格式： 组装外层分组字段+汇总字段
     *
     * @param groupSqlVO
     * @param groupColumnsList
     * @param split
     * @author zyy
     * @date 2023/2/15
     * @version v1.0
     */
    public void buildSubColumnOfCount(GroupSqlVO groupSqlVO, List<String> groupColumnsList,boolean split) {
        List<String> subQuerySqlOfCountList = groupSqlVO.getSubQuerySqlOfCountList();
        if(CollectionsUtil.isEmpty(subQuerySqlOfCountList)){
            return;
        }

        List<String> subColumnList = new ArrayList<>(subQuerySqlOfCountList);
        List<String> columnList = new ArrayList<>(groupColumnsList);
        columnList.addAll(groupSqlVO.getSummaryColumnAlisa());
        for (String groupColumn : columnList) {
            String column = groupColumn;
            if(split){
                String[] strings = groupColumn.split(XbbConstant.AS);
                column = strings.length == BasicConstant.TWO ? strings[BasicConstant.ONE] : groupColumn;
            }
            subColumnList.add(column);
        }
        groupSqlVO.setSubSqlOfCount(String.join(XbbConstant.SQL_COMMA,subColumnList));
    }

}
